Mostrando postagens com marcador Artigos. Mostrar todas as postagens
Mostrando postagens com marcador Artigos. Mostrar todas as postagens

Estilos de Arquitetura e Separação de Responsabilidades para um Design Ágil

quarta-feira, 1 de fevereiro de 2012

Com a grande demanda de profissionais por parte das empresas, muitos deles acabam sendo contratados sem ter o devido conhecimento sobre boas práticas de desenvolvimento de software, infraestrutura de desenvolvimento, protocolos de comunicação, sistemas gerenciadores de banco de dados e muitas vezes até conhecimento básico sobre sistemas operacionais.

Além disso, dentro das empresas existe uma demanda cada vez maior por projetos de software de alta complexidade, com prazos de entrega na maioria das vezes fora da realidade. O que faz com que muitos projetos sejam entregues sem testes, com falhas de implementação, qualidade duvidosa e muitas vezes sem atender ao negócio do cliente.

Como consequência, após implantado, o sistema passa a apresentar sérios problemas como degradação da performance, perda de dados, cálculos incorretos, entre outros problemas, trazendo grandes prejuízos à empresa e fazendo com que os usuários percam a confiança no sistema e por fim os próprios desenvolvedores.

Direcionado para este cenário, o presente artigo visa demonstrar boas práticas de desenvolvimento de software e explicar os princípios fundamentais para se criar um bom design. Veremos também a aplicação de alguns padrões de projeto pouco difundidos, mas que são de extrema importância no dia a dia do desenvolvedor.

Estilos de Arquitetura

Quando vamos planejar o desenvolvimento de um software, geralmente um dos primeiros itens que o arquiteto de software começa a analisar é qual o melhor estilo de arquitetura que se aplica ao
contexto do projeto. Neste ponto ele leva em consideração diversos fatores, como os requisitos do software, custo, infraestrutura e conhecimento técnico da equipe.

Entender o estilo arquitetural adotado para o desenvolvimento traz diversos benefícios para os desenvolvedores e para a empresa como um todo, entre eles: fornecer uma linguagem comum entre os desenvolvedores e os demais envolvidos no projeto.

Por exemplo, quando o estilo de arquitetura é SOA, os desenvolvedores podem até conversar com pessoas de outras áreas, que não possuem conhecimento técnico (como detalhes da linguagem de programação, servidores de aplicação, etc.), sobre o método envolvido na automação dos processos de negócio, que as mesmas entenderão sobre o que é um serviço, governança e, dependendo do usuário, até termos mais específicos, como escalabilidade.

A Tabela 1 apresenta um resumo dos principais estilos de arquitetura.

Estilo de Arquitetura
Descrição
Client-Server Também conhecida como arquitetura de duas camadas. Este tipo de arquitetura descreve a interação entre um ou mais clientes e um servidor, através de uma conexão de rede. A aplicação mais comum para esse tipo de arquitetura é um Banco de Dados no lado do servidor com a lógica da aplicação representada em Stored Procedures, e o lado do Cliente representado por aplicações conhecidas como Fat-Clients (Clientes Pesados), que muitas vezes contêm a lógica de negócio embutida no front-end. Como exemplo, podemos citar aplicações desenvolvidas com Delphi, Visual Basic, Oracle Forms, entre outros.
Arquitetura baseada em Componentes Quando utilizamos uma arquitetura baseada em componentes, decompomos o design da aplicação em componentes lógicos com um fraco acoplamento, de forma que cada um deles seja individual e reutilizável, com uma localização transparente e interface de comunicação bem definida. Uma das grandes vantagens desse tipo de arquitetura é que ela promove a reusabilidade dos componentes e facilita a manutenção da aplicação.
Domain Driven Design De acordo com o próprio criador, Eric Evans, DDD não é uma tecnologia e nem uma metodologia. DDD é um estilo de arquitetura orientado a objetos, focado em modelar o domínio do negócio e a lógica do domínio com o uso de técnicas, práticas e padrões de projeto.
Arquitetura em Camadas Esse é o estilo de arquitetura mais conhecido e mais utilizado para o desenvolvimento de aplicações. Ele permite a separação dos módulos do sistema em camadas (layers) diferentes. As principais vantagens desse estilo são a facilidade de manutenção, o aumento da extensibilidade, reusabilidade e escalabilidade.
3-Tiers/N-Tiers Esse estilo segrega as funcionalidades em segmentos separados de maneira similar ao estilo da arquitetura em camadas, mas com cada segmento alocado em camadas físicas (tiers) separadas, conforme veremos em detalhes no tópico “Arquitetura Distribuída”.
 Ele é ideal quando o projeto demanda escalabilidade. Para isso, as camadas lógicas (layers) da aplicação são alocadas em máquinas diferentes.
 Geralmente, ao mapear as camadas lógicas (layers) para as físicas (tiers), podemos criar um cluster ou um farm na mesma camada física para aumentar a performance e a confiabilidade da aplicação.
Arquitetura Orientada a Serviços(SOA) SOA já deixou de ser apenas uma palavra no meio de TI para se tornar um modelo consagrado adotado em muitas empresas. Uma arquitetura orientada a serviços nada mais é do que uma aplicação que expõe e consome as funcionalidades do sistema como serviços por meio de contratos e mensagens.
 Algumas das características de uma Arquitetura Orientada a Serviços são: a independência da Plataforma, comunicação baseada em serviços entre os componentes de software, integração de múltiplas funcionalidades em um único componente de interface do usuário e a exposição dos serviços por meio de repositórios ou catálogos.
Arquitetura Orientada a Objetos Ao aplicar esse estilo, o sistema é dividido em objetos individuais, reutilizáveis e autossuficientes. Cada objeto contém os dados e o comportamento pelos quais é responsável. Uma arquitetura orientada a objetos geralmente busca espelhar objetos do mundo real de modo a tornar simples a modelagem da aplicação.
Tabela 1. Estilos de Arquitetura.

Cluster: É um conjunto de computadores interligados que trabalham em conjunto como se fosse um único computador. Estes computadores são utilizados para suportar aplicações que têm necessidade de alta disponibilidade e alta capacidade de processamento.
Farm: Um Servidor Farm, também conhecido como Data Center, é um conjunto de servidores mantido (geralmente) por uma empresa para atender as necessidades computacionais da corporação, como o processamento de grandes volumes de informação, atender aos sistemas corporativos e prover servidores de contingência no caso de um problema no computador principal.
Repositório: Um Repositório é um local onde todos os clientes de um domínio específico publicam seus serviços, de maneira que todos os usuários passam a conhecer os serviços disponíveis e como acessá-los.
Para tanto, um repositório deve ter uma interface bem definida para publicação dos serviços, funções para localização, controle e maneira uniforme de acesso.

Uma vez que o estilo de arquitetura é definido, o passo seguinte é definir como as funcionalidades do sistema serão divididas, de forma a manter em conjunto os componentes relacionados (alta
coesão), e fazer com que estes possuam o mínimo de conhecimento sobre os outros componentes (baixo acoplamento). Para alcançar o baixo acoplamento e uma alta coesão é importante entender o conceito de Separação de Responsabilidades.


Separação de Responsabilidades (Separation of Concerns)

O termo Separação de Responsabilidades foi criado pelo pai do algoritmo de caminho mínimo, o cientista Edsger W. Dijkstra em 1974, e tem como objetivo dividir a aplicação em funcionalidade distintas com a menor similaridade possível entre elas. Para aplicar com sucesso este princípio, o mais importante é minimizar os pontos de interação para obter alta coesão e baixo acoplamento entre os componentes do sistema. Para tanto, é recomendado, primeiro dividir suas responsabilidades e organizá-las em elementos bem definidos, sem repetição de código ou de funcionalidade.

O tipo de separação de conceito mais difundido é o da separação horizontal, onde dividimos a aplicação em camadas lógicas de funcionalidades, como por exemplo, o protocolo TCP/IP (modelo OSI), que é separado pelas camadas de aplicação, transporte, rede, enlace e física. Neste modelo, cada camada tem sua própria responsabilidade e não precisa conhecer as camadas adjacentes. Voltando ao nosso mundo, em uma aplicação Java EE, as camadas mais conhecidas são a de Apresentação, Serviço, Domínio e Infraestrutura, como ilustra a Figura 1.


Figura 1. Separação Horizontal de Conceitos (Camadas lógicas de uma aplicação).

Podemos também aplicar o tipo de separação vertical, onde dividimos a aplicação em módulos ou funcionalidades que são relacionadas a um subsistema ou grupo de operações dentro de um sistema.
Veja um exemplo na Figura 2.

Figura 2. Separação Vertical de Conceitos.

Separar as funcionalidades de uma aplicação em módulos deixa claro as responsabilidades e dependências de cada funcionalidade, o que ajuda na execução dos testes e na manutenção do
software. Na Figura 2 fazemos um agrupamento por módulos; neste caso a separação foi feita pelos módulos de RH, Contábil e Marketing.

Além disso, podemos utilizar o conceito de separação vertical em conjunto com o conceito de separação horizontal. Veja um exemplo na Figura 3.

Figura 3. Aplicação da Separação de Conceitos Vertical e Horizontal.

Um papel importante da separação de conceitos é o da separação de comportamento, que envolve a divisão dos processos do sistema em unidades lógicas de código reutilizáveis e gerenciáveis. Ao organizar o comportamento, alcançamos os seguintes benefícios:
  • Eliminamos a duplicação de funcionalidades;
  • Minimizamos as dependências externas;
  • Maximizamos o potencial para reuso;
  • Restringimos o escopo do trabalho para os limites de cada módulo.
Como vimos, é importante entender a separação de conceitos pois ao modelarmos uma aplicação devemos ter conhecimento das responsabilidades de cada um de seus componentes. Além disso, devemos ter uma ideia de como será feita esta separação e como será feita a distribuição destes componentes na arquitetura disponível pelo cliente.

Para tanto, é preciso levar em consideração outros fatores, como infraestrutura e recursos disponíveis, conforme veremos a seguir, no próximo artigo da série.

Referências

Excelente artigo sobre separação de responsabilidades
http://www.aspiringcraftsman.com/2008/01/art-of-separation-of-concerns/

Biografia de Edsger Dijkstra.
http://pt.wikipedia.org/wiki/Edsger_Dijkstra

Guia de Arquitetura de Aplicações da Microsoft.
http://www.codeplex.com/AppArchGuide

Desenvolvimento Portlets: JSRs 168 e 286

quarta-feira, 12 de outubro de 2011

Duas JSRs, 168 e 286, atendem à criação de portlets. Em outubro de 2003 o JCP lançou a JSR-168, a primeira especificação que padroniza como os componentes devem ser desenvolvidos para os servidores de portal. Como as outras grandes JSRs, a JSR-168 possui o aval dos maiores fornecedores de portais. Esta especificação atende aos seguintes quesitos:

  • O contrato de contêiner de portlet e o gerenciamento do ciclo de vida do portlet; 
  • A definição dos estados das janelas e os modos do portlet; 
  • Gerenciamento das preferências do Portlet; 
  • Informações do Usuário como nome, endereço, e-mail, que podem ser informadas no arquivo de deployment descriptor e que podem ser recuperadas por um objeto Map através da constante USER_INFO definida na interface PortletRequest
  • Empacotamento e Deployment; 
  • Segurança; 
  • Tags para JSF. 
Mas, quando grandes fornecedores como a Apache, BEA, Borland, Oracle, IBM, SAP entre outros que fazem parte do expert group da JSR-168 começaram a criar as suas soluções de Portal, começaram a surgir também alguns problemas relacionados à limitação da especificação que antes não haviam sido detectados.
Conforme a adoção por soluções de portal baseadas na JSR 168 começou a aumentar, naturalmente o público consumidor destas soluções e o próprio negócio passou a demandar cada vez mais funcionalidades, que não haviam sido contempladas, fazendo com que soluções proprietárias fossem criadas pelos fornecedores. Entre as limitações da primeira versão da especificação de Portlets (JSR-168), podemos citar:
  • Falta de filtros para portlets (similar aos Filtros nos Servlets); 
  • Ausência de funcionalidades para a intercomunicação entre os portlets; 
  • Limitação do Escopo de Sessão do Portlet, onde a sessão do Portlet na JSR 168 se restringe apenas ao ID individual da aplicação e não da sessão do usuário do Portal. 
Essas limitações culminaram no lançamento da JSR 286, que define a segunda versão da API de Portlets. A JSR 286 incluiu novas funcionalidades como tratamento de eventos, envio e recebimento de parâmetros (permitindo a passagem de parâmetros entre os portlets), inclusão de filtros, suporte a Ajax e a disponibilidade de recursos do servidor, com o uso da interface ResourceServingPortlet.

Contrato do Contêiner e Gerenciamento do ciclo de vida do Portlet

A especificação da JSR-286 define um contrato para o contêiner de portlets. O contrato define quais métodos o contêiner deve chamar durante o ciclo de vida do portlet mediante o uso da interface javax.portlet.Portlet. O desenvolvedor pode implementar estes métodos para fornecer a funcionalidade desejada. Dessa forma, todo portlet tem que implementar esta interface, seja implementando-o diretamente ou estendendo uma classe existente que a implemente.
Os métodos do ciclo de vida executados pelo contêiner definidos pela interface javax.portlet.Portlet são apresentados na Tabela 1.

Método
Descrição
init()
Método executado quando o portlet for instanciado no contêiner.
processAction()
Chamado após o usuário submeter requisições ao portlet. É onde processamos os inputs disparados por uma ação do usuário do portlet.
render()
Chamado sempre que o portlet é reconstruído na tela.
destroy()
Executado no momento em que o contêiner destrói o portlet. Útil para liberarmos recursos que não estejam sendo utilizados, por exemplo, conexões com banco de dados.
Tabela 1. Métodos do ciclo de vida de um portlet

A especificação da JSR-286 ainda fornece interfaces opcionais para controle do ciclo de vida que o Portlet pode implementar como EventPortlet, que permite ao Portlet reagir às ações ou mudanças de estado oriundas da interação do usuário com o portlet ou ações originadas por outros portlets e a interface ResourceServingPortlet, utilizada para disponibilizar recursos do servidor no Portlet.

Portlet Modes e Window States

Para cada portlet existem dois itens de estado gerenciado, que são o modo do portlet (portlet mode) e o estado da janela (window state). Cada portlet possui um “portlet mode” corrente que indica a função que o portlet está realizando.
Os modes (ou modos) definidos na especificação são VIEW, EDIT e HELP. Estes modos são utilizados pelo método de renderização render(), conforme vimos na Tabela 1, para decidir qual método de visualização deve ser chamado. Os métodos de renderização chamados são apresentados na Tabela 2.

Método
Descrição
doView()
Método chamado por render() quando o portlet está em modo de visualização (VIEW). Deve conter a lógica que apresenta a página de Visualização para o portlet.
doEdit()
Chamado por render() quando o portlet está em modo de edição (EDIT).
doHelp()
Chamado por render() quando o portlet está em modo de ajuda (HELP) .
Tabela 2. Métodos de renderização do Portlet Mode

A classe PortletMode define constantes para estes portlet modes. A disponibilidade dos modos para o portlet pode ser restrito a roles (papéis) específicos de usuários do portal. Por exemplo, um usuário anônimo pode acessar o portlet apenas nos modos VIEW e HELP, enquanto que a role EDIT pode ser utilizada somente por usuários autenticados.
Outro tipo de estado gerenciado, o estado da janela (window state), apresenta a quantidade de informações que será disponibilizada para o portlet. A especificação define três tipos de estados para cada portlet, que são: normal, maximizado e minimizado. A classe WindowState possui constantes para estes estados da janela.
Para um maior entendimento, a Figura 1 apresenta estes conceitos de portlet mode e window state aplicados a um portlet.
Figura 1. Anatomia de um portlet
Opcionalmente o desenvolvedor pode especificar tipos customizados de modo e estado de janela, alterando o arquivo portlet.xml com uso da tag custom-window-state para estados de janela e custom-portlet-mode para modos.

JSF/Portlet Bridge

Como parte do projeto OpenPortal da Sun, foi criado o projeto JSF/Portlet Bridge, que tem como objetivo fornecer uma biblioteca de integração que permita que aplicações desenvolvidas com JSF possam ser executadas em um ambiente de Portlet.
Para atender à especificação de portlets, o JCP disponibilizou a JSR 301 para definir como um portlet 286 interage com os artefatos do JSF. A especificação foi para votação em Julho de 2006, mas somente em Janeiro de 2009 o draft da proposta final foi disponibilizada para o público.
Portlet Bridge é uma tecnologia utilizada por um portlet para fazer uma ponte (por isso o nome bridge) para um ambiente de execução, onde diferentes abstrações são utilizadas para processar as interações com o usuário ou para renderizar a interface gráfica.
O Portlet Bridge age como um engine tradutor entre o ambiente de portal e o sistema destino, neste caso, uma aplicação desenvolvida com o framework JSF. Ele ainda fornece uma abstração do ambiente de portal para o ambiente do bridge, deixando os desenvolvedores livres para executar aplicações Faces como portlets, sem a necessidade de conhecerem os detalhes das APIs de portlet e seu modelo de desenvolvimento.
A Figura 2 ilustra uma aplicação portlet utilizando o JSF/Portlet Bridge para executar páginas Faces como se fossem fragmentos de um portlet
Figura 2. JSF/Portlet Bridge entre uma aplicação Portlet e uma aplicação JSF.

Transformando sua aplicação JSF em um portlet

Para tornar uma aplicação JSF compatível com a JSR 168/286 é preciso fazer algumas alterações na aplicação antes de executá-la como um portlet.
Primeiro, para utilizar o JSF Portlet/Bridge é preciso efetuar o download da biblioteca jsf-portlet.jar no site java.net (ver ao final, em Referências) e copiá-la para o diretório WEB-INF/lib da aplicação JSF que você deseja executar como portlet.
Uma vez adicionado o arquivo .jar ao classpath da aplicação, é preciso adicionar o arquivo deployment descriptor portlet.xml para o portlet. Neste arquivo vamos informar a classe com.sun.faces.portlet.FacesPortlet para a tag portlet-class. Esta classe é a implementação da interface javax.portlet.Portlet fornecida pela biblioteca do JSF/Portlet Bridge, e é ela que fará o trabalho de converter as páginas JSF para páginas de visualização no Portlet.
É preciso também informar qual página queremos utilizar como página inicial do portlet, informando o parâmetro de portlet com.sun.faces.portlet.INIT_VIEW para a página desejada, conforme mostra a Listagem 1 entre as linhas 08 e 15.


    
        Portlet JSF
        Teste
        Portlet JSF/Portlet Bridge
        
        com.sun.faces.portlet.FacesPortlet
        
        
            Página inicial do Portlet 
            com.sun.faces.portlet.INIT_VIEW
            /index.jsp
        
        
            text/html
            VIEW
            EDIT
            HELP
        
        
            Portlet JSF
            JSF
        
    

Listagem 1. Portlet.xml de uma aplicação JSF
Para incluir a página de edição do portlet, o procedimento é similar. Nos parâmetros iniciais do arquivo portlet.xml, devemos incluir o parâmetro de portlet com.sun.faces.portlet.INIT_EDIT, conforme o trecho da Listagem 2. Essa ação fará com que o contêiner de portlets interprete a página JSF editar.jsp citada na listagem, como modo de visualização EDIT.


  Página de Edição do Portlet
  com.sun.faces.portlet.INIT_EDIT
  /editar.jsp

Listagem 2. Inclusão da página de edição JSF no portlet

O mesmo se aplica para a página HELP, com a inclusão do parâmetro com.sun.faces.portlet.INIT_HELP.
Além disso, se em nossa aplicação houver mais de uma página, podemos atribuir regras de navegação para cada uma destas páginas, e por ser uma aplicação JSF o modelo de navegação é o do próprio JavaServer Faces.

O modelo de navegação do JSF torna fácil o trabalho de definir a regra de navegação das páginas do projeto, com a utilização de apenas algumas linhas no arquivo faces-config.xml da aplicação JSF. Podemos indicar qualquer página do portlet como referência para navegação, conforme demonstra a Listagem 3.

Na Listagem 3, utilizamos o modelo de navegação declarativo do próprio JSF para definir a navegação de um portlet. Como não é o escopo deste artigo, não iremos explicar o funcionamento das regras de navegação do JavaServer Faces, mas apenas para ilustrar, nesta listagem definimos uma regra que ao ser disparada uma ação na página editar.jsp, a aplicação irá navegar desta página para a página index.jsp, se o resultado referenciado pelo componente que disparou a ação de navegação da página editar.jsp for success.

  /editar.jsp
  
    success
    /index.jsp
  

Listagem 3. Navegação entre páginas JSF em um portlet
Por fim, para executar a aplicação é preciso somente efetuar o deploy do arquivo WAR para o seu servidor de portal preferido.
WSRP
WSRP significa Web Services for Remote Portlets, ou web services para portlets remotos. WSRP é uma tecnologia definida pela OASIS, e propõe um padrão para web services visuais que podem ser plugados em ambientes de portal que estejam aderentes à especificação, ou seja, se em um web service padrão nós reutilizamos o serviço com WSRP, reutilizamos toda a interface gráfica.
OASIS: Consórcio global formado por grandes empresas de tecnologia da informação como IBM, SAP, AG, Sun Microsystems, que conduz o desenvolvimento, convergência e adoção de padrões para e-business e web services, produzindo diversas especificações e padrões relacionados a áreas como SOA, web services, processamento de XML, segurança da informação e supply chain. 
Atualmente a API WSRP está na versão 2.0 e possui um fluxo bem simples. O owner do portal ou da aplicação primeiro inclui em seu ambiente de portal um web service de terceiro (WSRP) dentro de um portlet. A partir deste momento, o portlet irá interagir com o conteúdo e com os serviços descritos no documento wsdl do WSRP, conforme veremos em detalhes mais adiante.

Um WSRP define:
  • Uma interface WSDL para invocação dos serviços WSRP; 
  • Como publicar, buscar, e efetuar bind dos serviços WSRP e metadados; 
  • Regras de fragmentação por marcação, para marcações emitidas pelos serviços WSRP. 
WSDL: Significa Web Service Definition Language, é uma linguagem baseada em XML utilizada para descrever web services. Além de descrever o serviço, um documento WSDL especifica os métodos e operações disponíveis e como acessá-los. 

WSRP é útil para o desenvolvimento web pois ele desacopla o deployment da entrega da aplicação, assim como fornece tanto os dados quanto a lógica de apresentação e requer pouca ou nenhuma programação para implementação do serviço. Além disso, WSRP fornece uma série de benefícios adicionais, como interoperabilidade e portabilidade. Normalmente um servidor de portal pode atuar como um produtor ou consumidor de WSRP.
Graças a essa interoperabilidade com o WSRP, podemos então rodar portlets Java remotos em uma ferramenta de portal que não seja em Java, como no Microsoft SharePoint.
Entre as desvantagens, estão a adoção ainda baixa por parte dos fornecedores, e a performance, que tende a ser baixa em grandes aplicações.

Como funciona?

Basicamente, um WSRP envolve dois componentes, além do portlet em si, conforme demonstra a Figura 3. A aplicação remota, conhecida como WSRP Producer, implementa os padrões de web services utilizando a especificação SOAP (Simple Object Access Protocol) sobre HTTP.
O WSRP Producer fornece um conjunto de operações para os consumidores do serviço, onde dependendo da implementação, o Producer pode tanto oferecer apenas um portlet quanto pode fornecer um ambiente para gerenciamento de diversos portlets. Resumindo, o WSRP Producer é um web service verdadeiro, com um WSDL e um conjunto de endpoints. Cada WSRP Producer é descrito utilizando um documento WSDL padrão.
O segundo componente é o WSRP Consumer, que é o cliente do serviço e que age como uma aplicação de portal para consumir o serviço baseado no arquivo WSDL do Producer.
Figura 3. Consumo de um WSRP

Interfaces do WSRP
Conforme explicado, WSRP define um conjunto de interfaces que todo WSRP Producer deve implementar e que todo WSRP Consumer utiliza para interagir com os portlets remotos. O grande benefício de se padronizar estas interfaces é a possibilidade de criar portlets genéricos. Isto garante que todo fornecedor de portal que queira suportar WSRP deve seguir a especificação.
A especificação WSRP propõe as interfaces definidas na Tabela 3.

Interface
Descrição
Obrigatório?
Service Description Interface (Interface de Descrição de Serviço)
Essa interface fornece uma descrição dos serviços fornecidos pelo Producer. Baseado nestas informações, o Consumer é capaz de determinar o que é preciso para executar o portlet, como por exemplo, inicializar um cookie antes que o Consumer interaja com qualquer um dos portlets.
Sim
Mark-up Interface (Interface de Marcação)
A Interface de Marcação permite que o Consumer interaja com o portlet remoto. Por exemplo, o Consumer poderia utilizar esta interface para realizar interações quando um usuário final submete um formulário a partir de uma página de portal. Além disso, o portal pode precisar obter a última marcação baseada no estado atual do portlet (por exemplo, quando um usuário atualiza o navegador ou inicia uma interação com outro portlet na mesma página).
Sim
Registration Interface (Interface de Registro)
Esta Interface permite que o Producer obrigue que os Consumers façam um registro antes de interagir com o serviço através do uso das interfaces de Service Description e Mark-up.
Não
Portlet Management Interface (Interface de Gerenciamento do Portlet)
Esta interface fornece acesso ao ciclo de vida do portlet remoto. Um Consumer poderia customizar o comportamento do portlet ou até mesmo efetuar uma chamada ao método destroy() mediante o uso desta interface.
Não
Tabela 3. Interfaces definidas na especificação WSRP

No mais é isso, 
Diversão Garantida!!!

Introdução a JAX–RS – Java API for RESTful Web Services

sábado, 16 de outubro de 2010

JAX-RS é a solução do JCP para o estilo de programação REST. A proposta final da especificação foi liberada para o público no inicio de Agosto de 2008,. A especificação define um conjunto de APIs Java para
auxiliar no desenvolvimento de web services baseados em REST.
O objetivo da API é fornecer um conjunto de anotações, classes e interfaces para expor uma classe POJO
como um web service RESTful, de modo que possamos fazer uma programação fácil e de alto nível.


Trabalhando com os recursos

Para uma classe ser determinada como um recurso, ela tem que ser uma classe POJO com pelo menos um método anotado com a anotação @Path.
A anotação @Path pode ser colocada na declaração de classe ou de um método e possui o elemento value
obrigatório. Por este elemento definimos o prefixo da URI que a classe ou o método irá atender. Na Listagem 01, a classe Repositorio é identificada pela URI relativa “/repositorio/{id}”, onde {id} é o valor do parâmetro id, fornecido junto a URI.
Mais adiante, demonstraremos como extrair valores como esse de uma URI utilizando anotações especificas.

@Path("/repositorio/{id}")
public class Repositorio { ... }
Listagem 01 - Mapeando uma URI para uma classe com @Path.

A especificação define que no ciclo de vida de um recurso, por padrão, sempre que for feito uma requisição a um recurso, será criada uma nova instância de uma classe REST. Primeiro o construtor é chamado pelo contêiner, por conta disto, o construtor da classe deve ser público. Após este primeiro passo, o contêiner efetua as injeções de dependência nos devidos métodos e o método designado para aquele recurso é invocado. E finalmente após a chamada ao método o objeto fica disponível para o garbage collector.
Geralmente a anotação @Path é incluída na declaração de um método quando queremos atribuir um caminho mais específico para um recurso, de forma a especializar nosso método, como na Listagem 02. Note no exemplo como a URI é mapeada com a classe e o método.
@Path("/vendas/")
public class Repositorio {
  @GET
  @Produces("application/xml")
  @Path("/pedidos/{numPedido}/")
  public PedidoAsXML getPedido(@PathParam("numPedido") Integer id){
    // retorna Pedido em formato XML.
  }
}
Listagem 02 - Mapeando uma URI para uma classe com @Path.

Acessando os Recursos

Para acesso aos recursos, a especificação JAX-RS define um conjunto de anotações correspondentes aos métodos HTTP, como @GET, @POST, @PUT, @DELETE, @HEAD.. Elas devem ser atribuídas a métodos públicos. O método anotado com @GET, por exemplo, irá processar requisições HTTP GET na URI atribuída. O comportamento do recurso é determinado pelo método HTTP ao qual o recurso está respondendo.
É bom entender o papel e o uso de cada um destes métodos HTTP no momento de projetar nossos serviços.
Além dos métodos definidos pelo JAX-RS, podemos criar uma anotação customizada como @MKCOL, com uso da anotação HttpMethod, conforme ilustra a Listagem 03.
Com esta anotação podemos criar métodos customizados e extender a gama dos métodos pré-existentes e utilizar os métodos definidos pelo WebDAV, como fazemos na Listagem 3, ou podemos alternar um método padrão para a anotação customizada, onde para isso poderíamos simplesmente informar como valor para anotação HttpMethod o valor do método que queremos sobrepor, por exemplo, para sobrepor o método PUT a declaração da anotação ficaria
@HttpMethod("PUT").

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@HttpMethod("MKCOL")
public @interface MKCOL {
}
Listagem 03: Utilizando a anotação HttpMethod para criar uma anotação customizada.

Representações: Quais são os sabores?

As classes de uma aplicação RESTful podem ser declaradas para suportar diversos tipos de formatos durante um ciclo requisição-resposta. Para isso a especificação define as anotações @Consumes e @Produces para o tratamento da request e response respectivamente.
Com estas anotações o servidor declara o tipo de conteúdo que será trafegado, através do cabeçalho (header) do protocolo HTTP, estas anotações podem ser aplicadas na declaração de uma classe, ou podemos utilizar estas anotações na declaração do método para sobrescrever a declaração da classe, na ausência destas anotações, será assumido como default qualquer tipo de retorno ("*/*").
No caso da anotação @Produces, ela é utilizada para mapear uma requisição de um cliente com o cabeçalho do cliente (parâmetro Accept). Desta maneira, podemos definir mais de um tipo de retorno da URI solicitada, como JSON e XML, como no exemplo da Listagem 04:
@GET
@Produces({"application/xml", "application/json"})
public PessoaConverter getPessoa(@QueryParam("CPF") String numCPF) {
  // Retorna representação em XML ou JSON
}
Listagem 04 - Declarando o tipo de retorno com a anotação @Produces.

Pegando o exemplo da Listagem 04, podemos testar o retorno da chamada utilizando uma das ferramentas
citadas no tópico "Como consumir serviços REST", como a ferramenta RESTClient, por exemplo, e incluir na aba "Headers" o parâmetro "Accept" e no campo Value especificar o tipo de retorno primeiro com XML e depois com JSON, conforme Figura 01:

Figura 01 - Testando tipos de retorno para a mesma URI com RESTClient.

Com a anotação @Consumes por outro lado, podemos definir os tipos de mídia que um recurso em particular consome. Como o exemplo da Listagem 05, onde estamos declarando que o método consome apenas formatos do tipo XML e JSON:
@PUT
@Consumes("application/xml","application/json")
@Path("/autores/")
public Response putPessoa(PessoaBinding pessoa) {}
Listagem 05: Uso da anotação @Consumes.

Extraindo parâmetros e valores da URI na requisição.

JAX-RS fornece algumas anotações para extrair informações de uma requisição. Existem seis tipos de parâmetros (ver Tabela 01) que podemos extrair para utilizar em nossa classe recurso. Para os parâmetros de query utilizamos a anotação @QueryParam. Para os parâmetros de URI(path) existe a anotação @PathParam.
Para os parâmetros de formulário existe @FormParam. Já para parâmetros de cookie existe @CookieParam.
Para os parâmetros de header existe @HeaderParam e, finalmente, para os parâmetros de matriz existe a anotação @MatrixParam.
Estas anotações podem ser aplicadas diretamente a parâmetros de um método. Desta forma vinculamos o valor do parâmetro de uma URI a algum parâmetro de entrada de um método. Para contextualizar, veja um exemplo na Listagem 06:
@Path("/editora/")
public class EditoraResource {
  @GET
  @Produces("application/xml")
  @Path("/autores/{nomeAutor}/")
  public PessoaBinding getPessoa(@PathParam("nomeAutor") String name,
                       @QueryParam("idade") int idade,
                       @HeaderParam("CPF") String numCPF,
                       @MatrixParam("statusCivil") String statusCivil) {
     return new PessoaBinding(name, idade, numCPF, statusCivil);
  }
}
Listagem 06 – Mapeando os parâmetros de uma URI para os parâmetros de um método.

Na Listagem 06, vemos a aplicação de várias anotações de parâmetro de URI em um único método. Para entender melhor como será feito o DE-PARA da URI para os parâmetros de entrada, vamos fazer uma chamada a este recurso com a biblioteca curl, apresentado na Figura 02.

Figura 02 - Fragmentando a URI para demonstrar anotações de mapeamento.



Tabela 01 - Anotações JAX-RS para extração de informações da URI.

No exemplo da Listagem 06 não demonstramos o uso das anotações CookieParam e FormParam, mas o seu uso é bem similar. No caso de FormParam, esta anotação pode capturar todos os valores submetidos de um formulário HTML e injetá-los nos parâmetros desejados. Veja um exemplo simples na listagem 07. Trata-se de um formulário HTML e de um método que irá receber estas informações.

Nome: Idade:
@Path("/editora/")
public class EditoraResource {
  @GET
  @Path("/autores/")
  public PessoaBinding getPessoa(@FormParam("nomeAutor") String name,
                       @FormParam("idade") int idade) {
    return new PessoaBinding(name, idade);
  }
}
Listagem 07 - Uso da anotação FormParam.

No caso da anotação CookieParam, conseguimos injetar o valor de cookie ou a classe Cookie do javax.ws.rs.core, que representa o valor de um cookie HTTP na invocação de um método.

Dados de Contexto

A especificação JAX-RS dispõe de um recurso para a obtenção de informações do contexto da aplicação e de requisições individuais. Estas informações são disponíveis tanto para as classes recursos quanto para os providers. Para a recuperação destas informações existe a anotação @Context, que ao ser aplicada sobre um campo, método ou parâmetro, identifica um alvo a ser injetado pelo contêiner.
O contêiner fornece instâncias dos recursos listados na tabela 02, mediante a aplicação da anotação @Context.


Tabela 02: Lista de recursos injetados pelo contêiner pela anotação @Context.

Tratando o retorno dos métodos ao Cliente.

Os tipos de retorno de uma chamada a um método recurso podem ser do tipo void, Resource, GenericType ou outro tipo Java. Esses tipos de retorno são mapeados ao entity body da Response cada um de uma maneira, de acordo o provider padrão, conforme veremos a seguir.
Para os retornos do tipo void, o retorno será um corpo vazio com status 204 do HTTP. Para tratar o retorno ao cliente foi disponibilizada a classe abstrata Response. Com essa classe definimos um contrato entre a instância de retorno e o ambiente de execução, quando uma classe precisa fornecer metadados para ambiente de execução.
Podemos estender esta classe diretamente ou, ainda melhor, podemos criar uma instância utilizando sua classe interna ResponserBuilder. Por essa classe podemos construir objetos do tipo Response, adicionar metadados, adicionar cookies, adicionar dados no Header, informar a linguagem, entre outras informações.
Na Listagem 08, no método putPessoa, fazemos uso do método Response. Note que não a instanciamos diretamente, pois ela é uma classe abstrata que implementa o padrão de projeto Builder.
Dentro do método, primeiramente efetuamos uma chamada ao método estático created, passando como parâmetro a URI que obtemos através da classe injetada UriInfo. Esta classe retorna o objeto ResponseBuilder, que é uma subclasse de Response, esta subclasse é utilizada exclusivamente para criar instâncias de Response.
Por ResponseBuilder ser uma classe de construção (Builder), podemos efetuar chamadas recursivas aos métodos de parametrização. Após a chamada ao método created, chamamos o método status, no qual atribuímos o código de status HTTP 202 (Accepted) e logo após atribuímos uma entidade à requisição, no nosso exemplo um código HTML simples, pelo método entity. Na chamada ao método type seguinte, especificamos o tipo de mídia trafegado, neste caso TEXT_HTML. No final fazemos uma chamada ao método build, que constrói o objeto Response.
E por fim o objeto GenericEntity representa uma entidade de um tipo genérico, muito útil quando precisamos retornar uma Response personalizada e reter informações genéricas. Pois informações de tipos genéricos são apagadas ao utilizar uma instância.

@Context protected UriInfo uriInfo;
@PUT
@Consumes("application/xml")
@Path("/MundoJava/update/")
public Response putPessoa(PessoaBinding pessoa) {
     String retorno = "Bem vindo "+pessoa.getNome();
     Response response = Response.created(uriInfo.getAbsolutePath()).
                                       status(Response.Status.ACCEPTED).
                                       entity(retorno).
                                       type(MediaType.TEXT_HTML).
                                       build();
     return response;
}
Listagem 08 – Tratando a Response do cliente.

Entity Providers

Entity providers fornecem serviços de mapeamento entre representações e seus tipos associados Java. Existem dois tipos de entity providers, MessageBodyReader e MessageBodyWriter.
A especificação JAX-RS define que para alguns tipos, o contêiner pode automaticamente serializar (marshal) e deserealizar (unmarshal) o corpo de diferentes tipos de mensagens, listados na tabela 03.
Tabela 03: Tipos de Mídia e seus tipos Java correspondentes.

Para requisições HTTP, podemos mapear o corpo da entidade para um parâmetro de método com uso da interface MessageBodyReader, para o tratamento das responses, o valor de retorno é mapeado para o corpo da entidade de um método HTTP com uso da interface MessageBodyWriter.
Pode ser que no desenvolvimento de nossas aplicações, estes tipos padrões não atendam a necessidade de negócio e tenhamos que lidar com tipos que não sejam suportados pelos tipos default, para contornar esta limitação, a API JAX-RS permite que a criação de Providers para Message Body customizáveis, com métodos para conversão de InputStream/OutputStream para objetos Java do tipo T.
Para criar nosso próprio provider customizado, a especificação disponibiliza a anotação @Provider, que ao ser aplicado sobre uma classe, estamos automaticamente registrando este classe junto ao contêiner. 
Porém, é importante ressaltar, que esta funcionalidade apesar de muito útil, pode ser tornar um problema em grandes projetos, que podem utilizar providers com o mesmo nome em diferentes bibliotecas, podendo ocasionar conflitos.
Caso a aplicação necessite de informações adicionais, como HTTP Headers ou um código de status diferente, o método pode retornar o objeto Response que encapsule a entidade. 
Veja um exemplo extraído de um sample da implementação de referência da Sun, o Jersey, na listagem 09, esta classe implementa um MessageBodyWriter para uma classe Properties.

@Produces("text/plain")
@Provider
public class PropertiesProvider implements MessageBodyWriter {
    public void writeTo(Properties p, 
            Class type, Type genericType, Annotation annotations[],
            MediaType mediaType, MultivaluedMap headers, 
            OutputStream out) throws IOException {
        p.store(out, null);
    }
    public boolean isWriteable(Class type, Type genericType, Annotation annotations[], MediaType mediaType) {
        return Properties.class.isAssignableFrom(type);
    }
    public long getSize(Properties p, Class type, Type genericType, Annotation annotations[], MediaType mediaType) {
        return -1;
    }
}
Listagem 09: Uso da tag @Provider.
Tratando Exceções

Para tratamento de exceções, a especificação JAX-RS define a exceção WebApplicationException que estende RuntimeExcetion, que pode ser lançada por um método de recurso, por um provider ou por uma implementação de StreamingOutput. Esta exceção permite que abortemos a execução de um serviço JAX-RS. 
Como parâmetro de construtor, podemos utilizar um código de status HTTP ou até um objeto Response. Veja um exemplo na listagem 10:

@GET
@Produces("application/xml")
@Path("/autores/{personName}/{idade: [0-9]+}/")
public PessoaBinding getPessoa(@PathParam("personName") String name, @PathParam("idade")
    int idade, @HeaderParam("CPF") String numCPF) {
    if (idade <= 0 || idade > 120){
        throw new WebApplicationException(Response.
                                          status(412).
                                          entity("Idade inválida!").
                                          build());
    }
  return new PessoaBinding(name, idade, numCPF);
}
Listagem 10: Uso de exceção com WebApplicationException.

Por padrão, quando uma classe JAX-RS ou um método provider lança uma exceção em tempo de execução, essa exceção é mapeada a um código de status HTTP adequado. Nós podemos customizar a nossa exceção conforme a necessidade, para isto, a especificação define a interface ExceptionMapper, com ela podemos criar nossos próprios providers e customizar este mapeamento, para tanto, a implementação desta interface deve estar anotada com @Provider. Veja um exemplo na listagem 11:

@Provider
public class IdadeInvalidaExceptionMapper implements ExceptionMapper{
  public Response toResponse(IdadeInvalidaException ex) {
    return Response.status(412).entity(ex.getMessage()).build();
  }
}
Listagem 11: Mapeando uma exceção Java para uma Response.

Na listagem 11 perceba que registramos a classe ExceptionMapper da mesma maneira que registramos MessageBodyReaders e MessageBodyWriters. Ao utilizarmos a exceção IdadeInvalidaException em um método RESTful como no método da listagem 12, o contêiner irá em tempo de execução identificar o provider e irá mapear esta exceção com IdadeInvalidaExceptionMapper.


@GET
@Produces("application/xml")
@Path("/autores/{personName}/{idade: [0-9]+}/")
public PessoaBinding getPessoa(@PathParam("personName") String name, @PathParam("idade")
int idade, @HeaderParam("CPF") String numCPF) throws IdadeInvalidaException {
    if (idade <= 0 || idade > 120)
       throw new IdadeInvalidaException("Idade Inválida!");
    return new PessoaBinding(name, idade, numCPF);
}
Listagem 12: Uso de exceção de negócio, que é mapeada para Response.
Assim como toda nova tecnologia, JAX-RS não é uma bala de prata, mas sabendo o momento de usá-la se torna uma ferramenta poderosa de integração, em termos de facilidade no desenvolvimento e requerer uma
infraestrutura mais leve, dispensando o uso de um middleware WS-*.
Use e abuse! Diversão garantida!

Introdução a Portais Corporativos

sexta-feira, 13 de agosto de 2010

Se buscarmos a definição de Portal no dicionário, na maioria delas veremos que ele é definido como “uma porta, portão ou entrada”. Quando falamos em Portais web, estamos nos referindo a sites especiais da web ou intranet, que são designados a agir como um gateway de acesso a outros sites.
Um portal agrega informações de múltiplas fontes e torna estas informações disponíveis para diversos usuários. Além de disponibilizar diversas fontes de informações, eles fornecem um guia de serviços que auxiliam os usuários a se direcionarem no meio de tantas informações na internet.
Mais especificamente, um portal não deve ser visto somente como gateway para outros sites, mas para todos os recursos acessíveis na rede, que envolve intranets, extranets ou a própria Internet. Em outras palavras, um portal oferece acesso centralizado para aplicações e todo conteúdo relevante para a empresa/usuários finais. Na Figura 1 apresentamos a arquitetura de um portal, formado por um servidor web, um contêiner de Servlets/Portlets e as aplicações (portlets) para o portal, conforme veremos em detalhes no decorrer do artigo.

Figura 1. Arquitetura de um portal

Durante muito tempo as ferramentas de portal foram ignoradas e até mesmo discriminadas por muitos programadores que achavam que elas eram de uso exclusivo para web designers. Mas com o surgimento da arquitetura orientada a serviços e a busca frenética das empresas em disponibilizar soluções mais baratas e produtivas, com o intuito de reduzir o Time-to-Marketing, esse tipo de ferramenta voltou com toda a força para fazer o que sempre fez: facilitar a vida de todos. A partir desta análise, mostraremos nesse artigo as vantagens do uso de uma ferramenta de portal, e qual o papel do programador neste contexto.
Segurança
A etapa mais cansativa e torturante para um desenvolvedor é ter que gastar seu tempo desenvolvendo módulos de segurança de uma aplicação, sendo que esses módulos geralmente são constituídos por telas de autenticação, tratamentos de usuários e grupos de usuário, utilização de repositórios LDAP, e em algumas vezes a integração com um autenticador para desfrutar do tão desejável Single Sign On .
Além de ter todas essas características, muitas vezes é necessário desenvolver soluções “self-service”, para que o administrador do ambiente de Portal tenha autonomia para gerenciar o repositório de usuários e dar permissões de uso para as funcionalidades da ferramenta.
Praticamente todas as soluções de portal possuem todo esse mecanismo pronto, possibilitando ao programador se dedicar somente no desenvolvimento das aplicações de automatização do negócio.
Conteúdo
No desenvolvimento completo de uma solução como uma “Intranet”, é comum ver que todo o tempo de desenvolvimento é gasto na criação de aplicações para gerenciamento de conteúdo, como funcionalidades de notícias, biblioteca de documentos, áreas institucionais e qualquer outra seção que necessita de um gerenciamento de informações por parte do usuário do sistema. Em um projeto deste tipo, também é comum que todas essas funcionalidades passem por uma governança editorial, e que inevitavelmente necessitem de um mecanismo de workflow. Essas são funcionalidades típicas nas ferramentas de portal, o que fez com que todos achassem que esse tipo de ferramenta só proporcionava esse benefício.
Há empresas que buscam outras soluções que vão além de um simples gerenciamento de conteúdo, indicando que elas devem ser mais robustas e possuir módulos de digitalização, transformação e busca de conteúdo. Esses sistemas, chamados ECM (Enterprise Content Management), muitas vezes dependem de uma ferramenta de portal para disponibilizar o conteúdo trabalhado. Este é só um exemplo de ferramenta que necessita de um portal como camada de visão. E a forma com a qual esse e outros tipos de ferramentas mostram suas funcionalidades é através dos chamados portlets.
Portlet
A internet fornece um conjunto de informações quase que ilimitado para diversos tipos de dispositivos. Com o advento da web foi criado um universo de padrões e protocolos de comunicação, recursos, e uma linguagem de marcação utilizada para apresentação (HTML). Mas a web e seus protocolos foram projetados para atender ao conceito de uma página como um pedaço estático único de informação, apresentado em um navegador, como uma entidade completa e inalterável. Para visualizar outra página, o usuário tem que chamar outra página.
Até o momento, diversos esforços têm sido feitos para superar esta limitação com o uso extensivo de código, como JavaScript/Ajax, ou alguma solução DHTML para trazer ao usuário uma experiência similar e até mesmo superior ao uso de uma aplicação desktop.
Portlet é uma maneira de superar a natureza “tudo ou nada” de uma página HTML. Para defini-los podemos dizer que os portlets são o núcleo dos serviços de um portal, onde uma ferramenta de portal utiliza os portlets como uma interface de apresentação plugável, ou seja, aplicações que podem ser adicionadas em qualquer página em um ambiente de portal, com o objetivo de fornecer qualquer tipo de informação na camada de apresentação.
O conteúdo gerado por um portlet é chamado de fragmento, que na verdade é um pedaço de marcação (ex: HTML, XHTML, etc.) aderente a certas regras, de forma que possamos agregar pedaços de vários fragmentos para gerar um documento.
A página de um portal é composta por um ou mais portlets, que são normalmente agregados com o conteúdo de outros portlets para formar uma página. O ciclo de vida de um portlet é gerenciado pelo contêiner de portlet, conforme veremos logo a seguir. Na Figura 2 apresentamos uma página de exemplo do portal open source Liferay, com a disposição de vários portlets.

Figura 2. Exemplo de uma página de portal
Se olharmos atentamente o conteúdo do navegador na Figura 2, veremos que a página é formada por diferentes janelas. Temos uma janela para um dicionário, outra para um RSS, uma terceira para um calendário, e por último uma para o Google Maps. Cada uma destas janelas representa um portlet. Ao analisarmos o detalhe de cada janela, vamos perceber que cada uma delas contém uma barra de título e alguns botões, incluindo os botões de maximizar e minimizar.
Na verdade, estas janelas são aplicações diferentes, desenvolvidas independentemente uma das outras. O programador desenvolve o portlet como uma aplicação web e empacota em um arquivo .war, e o administrador do portal efetua o deploy deste arquivo .war no servidor de portal e adiciona o portlet recém instalado em uma ou mais páginas do portal.
Pelo fato de você poder colocar o portlet em qualquer página, faz com que você possa reutilizá-lo a todo o momento no portal, até mesmo em uma mesma página. No caso da Figura 3, apresentamos uma página com várias instâncias de um mesmo portlet (Locadora).
Figura 3. Várias instâncias do mesmo portlet em uma página

Repare nesta figura que temos um mesmo portlet na página, mas com instâncias diferentes. A ferramenta de portal tem a responsabilidade de garantir sessões independentes da aplicação, mesmo estando todos na mesma página.
Contêiner
Portlets são executados em um contêiner de portlets. O contêiner fornece aos portlets o ambiente necessário para sua execução e gerenciam o seu ciclo de vida.
O contêiner de portlets recebe as requisições oriundas do portal para executar ações nos portlets em seu ambiente. É importante entender que contêiner de portlets não é responsável por agregar o conteúdo produzido pelo portlet que ele está hospedando, quem faz esta agregação é o próprio portal.
Figura 4. Fluxo de criação de uma página de portal
A Figura 4 acima, apresenta como funciona a construção da página de um portal. Podemos notar que os portlets rodam dentro do contêiner, que recebe o conteúdo gerado pelos portlets. Na seqüência, vemos que o contêiner retorna o conteúdo do portlet para o portal. Por último, o servidor de portal cria a página com o conteúdo gerado pelos portlets e envia para o dispositivo cliente, onde é renderizada (por exemplo, um navegador).
Contêiners de Portlet e Contêiners de Servlets
Os portlets possuem várias similaridades com os servlets, como ambos serem componentes gerenciados por um contêiner especializado, ambos gerarem conteúdo dinâmico, por ambos interagirem com um cliente web através de request/response HTTP. Entretanto, os portlets não podem ser tratados como servlets por conta dos seguintes fatores:
  • Geram somente fragmentos de página no método de renderização, e não documentos completos;
  • Podem somente ser invocados através de URLs construídas através da API de portlet;
  • Clientes web interagem com os portlets através do sistema de portal;
  • Possuem modos pré-definidos de portlet e estados de janela que indicam a função que o portlet está executando;
  • Possuem um tratamento de requisição refinado para action, eventos, requisições de renderização e requisições a recursos;
  • Não possuem acesso a certas funcionalidades fornecidas pelos servlets, como a URL de requisição do cliente ao Portal, ou atribuir o encoding de caracteres para a resposta ao cliente.
Por conta destas diferenças, o JCP decidiu criar para portlets um novo tipo de componente. Porém, ao formular a especificação de Portlets, o JCP procurou sempre que possível, potencializar o uso das funcionalidades fornecidas pela especificação de Servlets. Isto inclui deployment, classloading, aplicações web, gerenciamento de sessão e request dispatching. Por isso, diversos conceitos e partes da API de Portlets foram modelados a partir da API de Servlet.
Os objetos criados em uma aplicação de portal, como portlets, servlets e JSPs são empacotados como uma aplicação web comum (.war), e irão compartilhar o mesmo classloader, contexto de aplicação e sessão no ambiente de execução.
 
No próximo artigo sobre o assunto, vou falar sobre as JSRs 168 / 286 sobre a criação de Portlets. 

Consumindo e Testando Clientes REST

terça-feira, 29 de dezembro de 2009



A especificação JAX-RS é uma ótima opção para criar web services REST e fornece meios de desenvolver componentes server-side, mas não descreve como os desenvolvedores devem desenvolver seus componentes client-side em Java, e essa já é uma das promessas para a próxima release do JAX-RS.

Pelo fato de nossos serviços RESTful serem URIs e a forma de acesso a estes serviços serem os próprios métodos HTTP, podemos trabalhar diretamente com requisições HTTP ou utilizar bibliotecas para facilitar este trabalho. Felizmente é relativamente fácil trabalhar diretamente com requests e responses HTTP, e as linguagens mais populares de programação possuem métodos/bibliotecas HTTP, como por exemplo, urllib2 e httplib em Python, libcurl em PHP, HTTPWebRequest em C#, open-uri em Ruby, e o pacote java.net.* e o projeto HttpClient da Apache para Java, entre outros. Mas para qualquer linguagem que seja feito a requisição ao serviço RESTful, temos que passar por alguns passos, conforme segue:
  1. Montar os dados que irão trafegar pelo requisição HTTP, como a URI, HTTP header (se houver), e o método HTTP desejado.
  2. Formatar estes dados como uma requisição HTTP, e enviá-lo para um servidor HTTP apropriado.
  3. Efetuar o parsing dos dados retornados (XML, JSON, etc..) para as estruturas de dados que o seu programa precisa.

Para facilitar a pesquisa, montamos um pequeno guia, para os desenvolvedores e estudiosos que querem aprender um pouco mais sobre REST, onde iremos apresentar algumas bibliotecas para teste e consumo de serviços RESTful.

cURL

Se o intuito for apenas testar os serviços REST desenvolvidos e validar o retorno, o mais simples é utilizar ferramentas existentes na web como é o caso da biblioteca cURL, que é uma ferramenta de transferência de arquivos entre cliente-servidor desenvolvida em C, e suporta protocolos como HTTP, HTTPS, FTP, FTPS, etc.
 A listagem 1 apresenta alguns exemplos de como fazer uma requisição GET e POST com uso da biblioteca cURL, como podemos ver, ela não possui uma interface gráfica, sendo uma ferramenta de linha de comando.
 Fazendo uma requisição (GET), passando como parâmetro de headerv tipo de conteúdo json, (-H "Accept:application/json")


// Fazendo uma requisição POST, passando como  query parameter name = JumboComLtda
$ curl -d name=JumboComLtda http://localhost:8080/Contatos/resources/customers/2/cliente/

// Excluindo um registro com DELETE, pelo parâmetro –X
$ curl -v –X DELETE http://localhost:8080/Contatos/resources/customers/99/


Registro excluído com sucesso !


Listagem 1: Uso da biblioteca cURL.
 

Referências:

RESTClient

 RESTClient é uma aplicação Java própria para auxiliar nos testes de serviços RESTful, complementar a isto, ela pode ser utilizada para testar Web Services POX (Plain Old XML) sobre HTTP. Para utilizar, basta efetuar o download do arquivo jar (com dependências) da ultima versão, no momento que escrevo este artigo, a versão mais recente é a versão 2.3, e vem com duas opções.

A versão GUI, é uma aplicação Swing com diversas opções, e bem conhecida de quem trabalha com o RESTClient desde suas primeiras versões, e a outra versão "cli" é para execução batch de arquivos .rcq. Para começar utilizar a versão em Swing, basta digitar o seguinte comando (A aplicação requer Java 6 para rodar):
$java -jar restclient-ui-2.3-jar-with-dependencies.jar
 
Após executar a aplicação, deverá ser apresentado a tela conforme ilustra a Figura 1.


Figura 01 - Interface Swing do RESTClient.

Pela aparência da interface gráfica, podemos deduzir facilmente o modo de utiliza-lá, basta digitar no campo URL o caminho desejado, selecionar algum método HTTP na aba Method, e executar a consulta clicando no botão [>>]. O resultado será apresentando no bloco HTTP Response.


Funcionalidades

 Com RESTClient, podemos fazer qualquer tipo de requisição HTTP (GET, PUT, POST, DELETE, HEAD, OPTIONS, TRACE), ainda existe o suporte a SSL e a possibilidade de adicionar parâmetros de Header adicionais.
É possível salvar as requests, responses, e o Response Body (atráves do menu File > Save Request, ou Save Response, Save Response Body), o que é útil para testes de regressão, que podemos utiliza-los posteriormente na versão de linha de comando.
RESTClient ainda vem com o Conteiner Jetty embutido, que possui um Servlet que imprime os detalhes das requisições submetidas a ele. Para iniciar o servidor basta acessar o menu Tools > Opção Start Trace Server (subirá na porta 10101).

E por fim, uma das funcionalidades mais interessantes é o seu suporte integrado para testes, que podem inclusive ser escritos em Groovy, o suporte a testes é baseado no JUnit 3.x e os tests são atachados a cada requisição. Para iniciar os testes, na aba "Test Script", clique o no botão Insert Template, RESTClient irá criar o código para você, conforme mostra a Listagem 02:
// The test class name should end with `Test'--this is a convention:
public class TemplateClassTest 
    extends org.wiztools.restclient.RESTTestCase{

  // Test method names should start with `test':
  public void testStatus(){
    if(response.getStatusCode() != 200){
      fail("This will fail the test!");
    }
  }
}
Listagem 2: Template de Test gerado pelo RESTClient.

A partir da versão 2.3, RESTClient possui uma versão em linha de comando, está versão é utilizada para executar requisições de forma batch e armazenar o resultado dos testes.  Para executar está versão, basta na linha de comando executar:

$java -jar restclient-cli-2.3-jar-with-dependencies.jar -o /temp/diretorioResponse *.rcq

Esse comando, irá executar todos as requisições contidas nos arquivos de extensão (.rcq) no diretório de execução atual, e irá salvar as responses (na extensão .rcs) no diretório /temp/diretorioResponse. E por fim, o RESTClient, imprime um resumo da execução dos testes. 


Referências:

Testando Web Services RESTful no NetBeans.

 Para quem é usuário do NetBeans, uma outra opção para testar Web Services RESTful é utilizar o suporte do próprio IDE, com um projeto Web criado e os serviços RESTful devidamente configurados, é possível testá-los clicando com o botão direito do mouse em cima do projeto e selecionar a opção “Test RESTful Web Services” (Figura 02), lembrando que está opção só estará disponível, se o projeto WEB possuir serviços WEB.


Figura 02 -Suporte a REST no NetBeans.

Ao selecionar esta opção, será feito o build e o deploy da aplicação web, e ao final do processo será disponibilizado uma página de testes web, como mostra a Figura 03.



Figura 03 - Tela de testes de Web Services RESTful

Na página apresentada é possível testar todos os serviços disponíveis, criar novos parâmetros para a requisição (botão “Add Parameter”), e também é possível selecionar o tipo de método HTTP para teste e o tipo MIME de retorno.

Para iniciar o teste, basta clicar no botão “Test”, após a execução, dentro da seção Response, podemos analisar os dados de retorno, os dados do cabeçalho e o status da chamada.

Além disso, de acordo com os serviços criados, o NetBeans ainda gera o arquivo WADL, visível no canto superior esquerdo da Figura 03.
 
Referências:

JAXB

JAXB (Java Architecture for XML Binding) fornece a API, as ferramentas e um framework que automatiza o mapeamento entre documentos XML e objetos Java. Ou seja, fornece compiladores que compilam Schemas XML para objetos Java. Em tempo de execução podemos deserializar (unmarshal) o conteúdo de um arquivo XML para representações Java.

Além disso, podemos acessar, alterar e validar a representação Java contra regras de um Schema e por fim, podemos serializar (marshal) o conteúdo de um objeto Java em conteúdo XML. Veja sua arquitetura na Figura 04:




Figura 04 - Overview do JAXB.

Esta fora deste artigo um estudo mais aprofundado sobre o JAXB, mas apenas para conhecimento, a API JAXB acabou se tornando a forma padrão de mapeamento entre Java e XML, com JAXB temos anotações que nos permitem criar uma representação em Java de um Schema XML, estas anotações estão presentes no pacote javax.xml.bind.annotations, e possuem anotações associadas a pacotes Java (@XmlSchema, @XmlSchemaType, etc..), a classes Java (@XmlType, @XmlRootElement), a propriedades e campos (@XmlElement, @XmlAttribute), entre outras anotaçõe.

Para exemplificar, considere o exemplo da listagem 3, esta é uma classe POJO representando uma pessoa, com anotações JAXB.  Ao fazer um marshalling de uma instância da classe PessoaBinding para XML, teremos o resultado apresentado na listagem 04.

@XmlRootElement(name="pessoa")
@XmlType(name="", propOrder={"nome","idade","statusCivil"})
public class PessoaBinding {
/* Construtores e Setters omitidos */
    private String nome;
    private int idade;
    private String statusCivil;
    private String cpf;

    @XmlElement
    public String getNome() {
        return nome;
    }
    @XmlElement
    public int getIdade() {
        return idade;
    }
    @XmlAttribute(name="num_cpf")
    public String getCpf() {
        return cpf;
    }
    @XmlElement
    public String getStatusCivil() {
        return statusCivil;
    }
}
Listagem 03 - Classe PessoaBinding com anotações JAXB.

   
       Wagner
       29
       Casado
   
Listagem 04 - XML Gerado após marshalling de classe JAXB PessoaBinding.

A especificação do JAX-RS fornece alguns Entity Providers padrões, entre eles, provedores para JAXB, para quando o tipo de conteúdo trafegado for do tipo xml (application/xml, text/xml e application/*+xml), de modo que o programador não precisa criar código para converter um objeto Java em código XML e vice versa, facilitando muito nossa vida.


Ainda na classe PessoaBinding da  listagem 03, poderíamos então, no nosso exemplo, criar um serviço RESTful cujo retorno seja a classe JAXB PessoaBinding , neste caso a declaração do serviço seria similar ao método da listagem 05.

    @GET
    @Produces("application/xml")
    @Path("/NetFeijao/autor/{idPessoa}/")
    public PessoaBinding getPessoa(@PathParam("idPessoa") Integer id) {
         return dao.getPessoaAsBinding(id); // Retorna uma entidade Pessoa como PessoaBinding
    } 
Listagem 05 - Serviço RESTful cujo retorno é uma classe JAXB.

Ao fazermos o consumo deste serviço RESTful, vamos perceber que a conversão é feita automaticamente pelo entity provider padrão para XML (veja o teste na Figura 05, utilizando a ferramenta RESTClient). De maneira inversa poderíamos criar um serviço RESTful para receber requisições PUT e receber como parâmetro de entrada do método a classe PessoaBinding via HTTP Body.  Conforme apresenta a listagem 06:





Figura 05 - Retorno do serviço RESTful cujo retorno é uma classe JAXB.

    @PUT
    @Consumes("application/xml")
    @Path("/NetFeijao/")
    public void putPessoa(PessoaBinding pessoa) {
        // Operação de update
    } 
Listagem 06 - Convertendo código XML para objeto JAXB em chamada PUT com REST.



Referências:

JAKARTA COMMONS - HTTP CLIENT

HttpClient é um subprojeto open source da Jakarta Commons que se tornou independente em 2007, e que foi concebido para facilitar o desenvolvimento de aplicações que utilizam o protocolo HTTP.
 Ele é um projeto escrito totalmente em Java, e implementa todos os métodos HTTP (GET, POST, PUT, DELETE, HEAD, OPTIONS e TRACE).

Possui suporte ao protocolo HTTPS, suporte ao gerenciamento de conexões para uso em aplicações multi-thread, suporte a cookie, possui mecanismos de autenticação Basic, Digest e criptografia NTLM.

 Na listagem 07, demonstramos o uso da biblioteca HttpClient, onde consumimos dois serviços RESTful, um com uma chamada GET e outra com uma chamada PUT.

     public void testHTTPClient() {
        try {
            HttpClient client = new HttpClient(new MultiThreadedHttpConnectionManager());
            client.getHttpConnectionManager().getParams().setConnectionTimeout(30000);
            final String CONTENT_TYPE = "application/xml";
            final String CHARSET = "UTF8";

           /* Executando chamada com método HTTP GET */
        String getURI = "http://localhost:8080/ProjetoREST/NetFeijao/autores/Wagner/?idade=29";
        GetMethod get = new GetMethod(getURI);
        Header meuHeader = new Header("CPF","123456789");
        get.setRequestHeader(meuHeader);
        int statusCodeGET = client.executeMethod(get);
        String responseBody = get.getResponseBodyAsString();
        System.out.println("Chamada GET");
        System.out.println(" Status Code: "+statusCodeGET+" \nResponse Body:\n"+responseBody);

         /* Executando chamada com método HTTP PUT */
       String putURI = "http://localhost:8080/ProjetoREST/NetFeijao/autores/update/";
       PutMethod put = new PutMethod(putURI);
    StringRequestEntity requestEntity = new StringRequestEntity(responseBody, CONTENT_TYPE, CHARSET);
        put.setRequestEntity(requestEntity);
        int statusCodePUT = client.executeMethod(put);
        responseBody = put.getResponseBodyAsString();
        System.out.println("Chamada PUT");
        System.out.println(" Status Code: "+statusCodePUT+" \nResponse Body:\n"+responseBody);
    } catch (Exception ex) {/* OMITIDO */}
}
Retorno da chamada ao método.
Chamada GET
 Status Code: 200
Response Body:

  
       Wagner
       29
       Casado
  


Chamada PUT
 Status Code: 202
Response Body:

Bem vindo Wagner


Listagem 07: Consumindo serviços REST via GET e PUT com HTTPClient.

Primeiro, na linha 3 instanciamos a classe HttpClient que é o nosso agente HTTP que irá conter os atributos de persistência com cookies, e credenciais de autenticação através da classe HttpState. E também onde será armazenado uma ou mais conexões HTTP, cujo qual faremos chamadas aos métodos HTTP.

Na linha 4 atribuímos um timeout para a conexão de 30 segundos. Depois nas linhas 5, 6 e 9 declaramos as variáveis quer irão determinar o tipo de conteúdo, o character set e a URI de acesso ao serviço REST.

Na linha 10, instanciamos a classe GetMethod, que como o próprio nome indica representa o método GET, passando como parâmetro a URL do nosso serviço RESTful (getURI). Na linha 11 criamos um objeto Header, passando como parâmetro no construtor a chave e o valor que representam o parâmetro e o valor do cabeçalho, no nosso exemplo, passamos um número fictício de CPF. Na linha 12 atribuímos o objeto header para o objeto GetMethod.

 Na linha 13, fazemos a chamada ao serviço RESTful via HTTP GET, e armazenamos o código de status do retorno na variável statusCodeGET, na linha 14 extraímos os dados da Response como String para a variável responseBody. Pelo fato do retorno ser em XML, poderíamos facilmente utilizar JAXB para trabalhar o retorno como um objeto Java. Finalmente nas linhas 15 e 16 imprimimos no console o retorno da chamada a estes métodos.

A partir da linha 18, iniciamos o mesmo processo, mas agora para efetuar uma chamada via método PUT, as únicas diferenças, são o uso do método PutMethod, que implementa o método HTTP PUT e o uso da classe StringRequestEntity na linha  21,  com esta classe atribuímos uma entidade como String ao método PUT que será enviado junto a requisição.

Nas linhas 25 e 26 imprimimos o retorno da requisição PUT.

JavaScript:




Graças ao objeto XMLHttpRequest conseguimos nos comunicar com servidores de forma assíncrona,   desde então temos todas as vantagens do AJAX ao nosso dispor.  Para quem desenvolve interfaces WEB, este recurso resolveu grandes problemas no lado do cliente, mas vale lembrar que JavaScript não é Java, não possui threads, nem tipos, e possui uma grande gama de frameworks Ajax, como por exemplo Prototype, JQuery, Dojo, Script.aculo.us, Ext-JS, entre outros.

 Na listagem 08, temos um exemplo de uma função em JavaScript  que consume um serviço RESTful cujo retorno é um XML.




var xmlHttp;
function showCustomer(str){ 
    xmlHttp=GetXmlHttpObject(); // omitido código do método0
    if (xmlHttp==null) {
        alert ("Your browser does not support AJAX!");
        return;
    }
    var url='http://localhost:8080/Contatos/resources/customers/58/';
    xmlHttp.onreadystatechange=stateChanged;
    xmlHttp.open('GET',url,true);
    xmlHttp.send(null);
}

function stateChanged() { 
    if (xmlHttp.readyState==4){
        var xmlDoc=xmlHttp.responseXML.documentElement;
        document.getElementById("nome").innerHTML= 
        xmlDoc.getElementsByTagName("name")[0].childNodes[0].nodeValue;
    }
}
Listagem 08 - Consumindo um serviço RESTful (retorno XML) com Ajax.

Na listagem 08, vimos um exemplo de um serviço que retorna XML, mas uma das grandes vantagens dos serviços REST, é que podemos trabalhar com diversos formatos para troca de informação de um mesmo recurso. Entre eles JSON.

jQuery



JQuery é uma biblioteca JavaScript que vem chamando atenção por conta de sua facilidade de desenvolvimento, ela simplifica muito a manipulação dos elementos de um documento HTML, o tratamento de eventos e as interações Ajax para prover um desenvolvimento rápido de aplicações web, livrando o desenvolvedor de preocupações relacionadas a compatibilidade de navegadores e aderência a CSS.

A biblioteca jQuery fornece algumas funções para tratamento de requisições Ajax, ideais para o consumo de serviços REST, que reduzem muito a complexidade e a quantidade de linhas necessárias para consumir um serviço REST.  Com a função $.ajax() do jQuery, conseguimos um alto nível de controle nas requisições ajax.

A sintaxe do comando é $.ajax(options), onde o parâmetro options são as propriedades que passamos para controlar como a requisição é feita e retorno da chamada.
Na listagem 09, demonstramos o uso das funções $.ajax().
$.ajax({
    type: ‘DELETE’,
    url: "http://localhost:8080/ProjetREST/NetFeijao/autores/"+idAutor+"/",
    success: function(msg){
        $("#alert").html(msg);
    }
});
Listagem 09 - Consumindo um serviço REST com a função $.ajax().

Na listagem 09, usamos dois parâmetros na função $.ajax(), o parâmetro type para indicar o método HTTP que queremos executar e a url de chamada.

Para tratar tipos de retorno JSON, o jQuery oferece a função $.getJSON(), utilizada para carregar dados JSON mediante uma requisição HTTP GET.

Na listagem 10 mostramos um exemplo de uso da função $.getJSON() em um serviço REST do Flickr, nós fazemos uma chamada ao serviço REST e passamos o retorno da chamada ao método de callback. Dentro da função de callback criamos a tag passando como valor o endereço da foto retornada pelo serviço REST e a incluímos na div #foto. Note que a variável data, é um map chave-valor dos dados retornados pela função REST.
$.getJSON("http://api.flickr.com/services/rest/?method=flickr.photosets.getPhotos& photoset_id=72157614488723406&format=json&jsoncallback=?",
function(data){
    $.each(data.photoset.photo, function(i,item){
        if (item.title == foto){
            $("").attr("src", "http://farm"+item.farm+".static.flickr.com/"+item.server+"/"+item.id+"_"+item.secret+"_m.jpg").appendTo("#foto");
        }
    });
});
Listagem 10 - Uso da função $.getJSON para consumo de dados no formato JSON.

É isso aí, consumir serviços REST é diversão garantida !!! E a todos um Feliz Ano Novo repleto de código \o/ !!!