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!!!

1 comentários:

Tiago Augusto Coelho disse...

Parabéns, ficou muito bom o post.