Oracle BPM com JSP e Ajax
Nos projetos de BPM que tenho participado utilizando o Oracle BPM como solução BPMS, dificilmente faço o uso de presentations, é muito mais comum eu optar em utilizar páginas JSP como camada de apresentação dos meus processos. Isso se dá pelo fato de que as presentations são bastante limitadas, e quando se faz por necessário ter interfaces mais elaboradas e customizadas, o JSP passa a ser a melhor opção.
Usando JSP, um novo leque de opções passou a existir e uma dessas opções passou a ser a possibilidade de usar Ajax. Ajax, para quem nunca ouviu falar, não é uma linguagem, uma API, tão pouco um framework, Ajax é o acrônimo de Asynchronous Javascript And XML e nada mais é que um conjunto de técnicas usadas para criar aplicações web interativas (RIA). Um dos pilares do Ajax é permitir comunicação assíncrona entre cliente e servidor utilizando requisições HTTP.
O Oracle BPM oferece uma maneira bem interessante de usar Ajax nas páginas JSP, mesmo não sendo nativa e também não tendo nada a respeito dizendo na documentação, é possível fazer a integração da camada de apresentação de um processo BPM com o próprio processo de uma maneira bem tranquila.
Para exemplificar isso melhor, criei um projeto bem simples no Oracle BPM, que na verdade só serve para mostrar como funciona essa integração entre páginas JSP e métodos dentro de um BPM Object através de Ajax.
Primeiros passos
Para começar, criei um BPM Object bem simples, que possui 3 atributos: name (String), mail (String), documents (String[]). Os dois primeiros atributos, que representam o nome e o email de alguém, são do tipo String e o terceiro atributo, que no caso representa os documentos de uma pessoa, é do tipo Array de String. Chamei esse objeto de: BpmObject.
Nesse mesmo objeto (BpmObject), criei ainda um método, esse método será responsável por retornar os documentos de um usuário. Na verdade esse é o método que irei chamar via requisição Ajax através de uma página JSP. O nome desse método ficou definido como getDocuments().
No futuro precisarei alterar esse objeto, mas eu explico depois.
Criando a página JSP
No Oracle BPM, para informar que a apresentação de determinado BPM Object deva se dar por meio de uma página JSP, se faz por necessário a utilização de Screenflows. Screenflow é um fluxo semelhante ao de um processo normal, mas a principal diferença é que o mesmo é executado por um participante único, ou seja, dentro de um Screenflow não existem lanes.
Após ter criado um processo normal, apenas com uma atividade do tipo Global Creation (para criar uma instância do processo) e também com uma Interactive Activity (para apontar para o Screenflow), parti para criação do Screenflow de fato. O Screenflow em questão, será tão simples quanto o processo no qual ele está associado, no caso contará apenas com uma única atividade do tipo Interactive Component Call, que será a responsável por “chamar” uma página JSP associando-a ao BPM Object criado no passo anterior.
Para chamar uma página JSP, se faz por necessária associar um BPM Object a mesma, então nesse caso criei um váriavel de instância do tipo BpmObject (o mesmo criado no primeiro passo) e dei o seu nome de bpmObject. Após isso, criei uma página JSP dentro de: /projetoBPM/webRoot/customJSP/ajaxPage.jsp.
O nome da página em questão é ajaxPage.jsp, e por enquanto ela irá possuir o seguinte código:
<%@ page session="true"%>
<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c"%>
<%@ taglib uri="http://fuego.com/jsp/ftl" prefix="f"%>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Teste Ajax/title>
<script type="text/javascript" src="<f:webResources relativePath='js/prototype-1.6.0.3.js'/>"></script>
</head>
<body leftmargin="0" topmargin="0">
Teste Ajax
<br/><br/>
Nome: <c:out value="${bpmObject.nome}" />
<br/><br/>
<div id="teste"></div>
</body>
</html>
Então, relembrando os passos até aqui:
1) Criação de BPM Object com 3 atributos e um método;
2) Criação de processo com uma atividade do tipo Global Creation e outra do tipo Interactive Activity;
3) Criação de Screenflow;
4) Associação (Implementation Type) da Interactive Activity do processo ao Screenflow criado;
5) Criação de atividade do tipo Interactive Component Call no Screenflow;
6) Criação de váriavel de instância no Screenflow com o tipo sendo o mesmo do BPM Object que foi criado no primeiro passo;
7) Definição do Implementation Type da Interactive Component Call como BPM Object Interactive Call;
8) Associação do BPM Object criado como váriavel de instância da Interactive Component Call do Screenflow;
9) Definição da página ajaxPage.jsp como JSP Presentation da Interactive Component Call do Screenflow.
Feito os passos acima, a estrutura do processo está pronta para criação da página JSP que irá fazer a requisição via Ajax a um método do BPM Object que foi criado no primeiro passo.
Fazendo a requisição Ajax e explicando alguns components da taglib do Oracle BPM
Para criação do mecanismo que irá fazer a requisição Ajax, se faz por necessário a utilização da taglib do Oracle BPM, sem ela não seria possível usar Ajax, ou então seria bastante árduo fazer tal integração.
Por exemplo, para incluir a biblioteca Prototype, que no caso será a responsável por fazer o “trabalho sujo” e criar o objeto XMLHttpRequest para fazer a requisição assíncrona, utilizei a tag f:webResources (linha 10). Esta tag inclui os resources inclusos no projeto BPM, sem que seja necessário informar explicitamente o context path da aplicação para inclusão de imagens, CSS ou Javascripts.
Outra tag importante é a f:invokeUrl, que no caso irá gerar a URL para execução de um método dentro de um BPM Object. Dessa forma, a página JSP precisa ser alterada, pois agora irá contar com uma função Javascript que irá fazer a chamada via Ajax ao método getDocuments() do BPM Object criado no primeiro passo, retornando o output do método para div teste.
Página JSP alterada:
<%@ page session="true"%>
<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c"%>
<%@ taglib uri="http://fuego.com/jsp/ftl" prefix="f"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Teste Ajax/title>
<script type="text/javascript" src="<f:webResources relativePath='js/prototype-1.6.0.3.js'/>"></script>
<script>
function callAjaxMethod () {
var bpmUrl ='<f:invokeUrl var="bpmObject" methodName="getDocuments" />';
return bpmUrl;
}new Ajax.Updater('teste', callAjaxMethod());
</script>
</head>
<body leftmargin="0" topmargin="0">
Teste Ajax
<br/><br/>
Nome: <c:out value="${bpmObject.nome}" />
<br/><br/>
<div id="teste"></div>
</body>
</html>
Repare que foi criada a função JS callAjaxMethod. Abaixo dessa função existe ainda a função JS Ajax.Updater, que no caso é uma função da biblioteca Prototype que irá fazer a chamada ao método do BPM Object, retornando seu output para a div teste.
Criando um output para o método getDocuments do BPM Object
Finalmente essa é a última parte desse pequeno tutorial. Agora a única coisa que falta é criar um output para o método do BPM Object que irá ser chamado via requisição Ajax.
Antes de mais nada, preciso dizer algo a respeito da tag f:invokeUrl, pois para ela funcionar corretamente existem algumas peculiariades.
Para um método de um BPM Object ser reconhecido por esta tag, ele deve ter uma das quatro assinaturas abaixo:
- methodName(Fuego.Net.HttpRequest request, Fuego.Net.HttpResponse response)
- methodName(java.util.Map requestParameters, java.util.Map requestHeaders)
- methodName(java.util.Map requestParameters)
- methodName()
No caso, eu optei por utilizar a primeira opção, pois para usar a função Ajax.Updater da Prototype, eu preciso escrever diretamente no output do método, ao invés de setar as informações necessárias através dos seus atributos.
Em virtude disso, o método getDocuments do objeto BpmObject agora passará a ter a seguinte assinatura:
getDocuments(Fuego.Net.HttpRequest request, Fuego.Net.HttpResponse response)
Agora, finalmente o código do método getDocuments, que ficará da seguinte maneira:
for (String doc : documents) {
response.bodyTextContent(arg1 : doc);
}
No código acima, estou percorrendo o atributo documents (array) e imprimindo no output todos os documentos definidos para aquele atributo, dessa forma, quando a função callAjaxMethod é chamada na página JSP, ela automaticamente chama (assincronamente) este método contido dentro do BPM Object, imprimindo todos os documentos definidos para dentro da div com o ID teste.
Conclusão
Utilizando os recursos corretos do Oracle BPM, como sua taglib e seus componentes, não é muito difícil fazer uma tela de apresentação mais interativa usando Ajax. No exemplo acima, foi criado um projeto bem simples, apenas para ilustrar, com o intuito de mostrar a atualização do conteúdo de uma div feita assincronamente através de uma requisição Ajax.
Se você gostou desse tópico, por favor considere deixar um comentário ou se inscreva no feed e tenha no futuro todos os tópicos entregues diretamente no seu agregador.








Marcus, muito bom e interessante. Isso dá uma boa visão da flexibilidade que podemos alcançar com um UI em JSP. Em breve quero postar umas dúvidas sobre essa utilização. Parabéns
Excelente iniciativa Marcos.
Marcos estou com uma dúvida sobre o seu wizard.
Realizei todas as etapas descritas por você, mas no momento de escrever o metodo getDocuments() o editor do BPMStudio 10.1.3… não reconheceu o código que você deixou como exemplo. Existe alguma coisa a mais para ser feita? Existe a necessidade de criar alguma variável? Existe algum passo que não foi descrito e que eu deveria ter feito?
Obrigado!
Marcos, o editor do BPMStudio não reconheceu a assinatura do método getDocuments(), também não reconheceu o comando for. Existe algo mais a ser feito?
Agradeço desde já sua ajuda.
Claudio,
Veja na sua ferramenta se o seu código (method editor) está como Java ao invés de PBL, é muito provável que o erro esteja aí.
Abraço,
Marcus, o problema é que o nome do metodo tem o mesmo nome da variavel (java beans), sendo assim não sei como alterar a assinatura no “read access”.
Abs
Muito bom artigo e de boa iniciativa…
Estou com outro problema… usar Ajax para acessar WebServices, ainda não sei o porque não funciona quando uso o mesmo mecanismo para acessar em método de WebService externo…
Se alguém já passou pelo problema e sabe o motivo de não funcionar, por favor, poste aqui, se eu descobrir algo deixo aqui para consulta.
Fala meu amigo.
Lembra de mim? Pantoja da Ideais? Amigo do Franklin!
Antes de mais nada, meus parabéns pelo blog cara, tem muita coisa boa aqui pra usar de referência.
Atualmente estava precisando exatamente disso pro que estou fazendo. O problema é que meu retorno não seria uma simples String, mas gostaria retornar um BPMObject ou pelo menos os atributos dele, e assim popular os campos do meu form. Talvez uma possível solução seria serializar meu BPMObject pra Json ou XML e recuperar no Javascript, não sei se é a que melhor se aplica.
Tem alguma ideia de como fazer isso?
Abração cara!
Pantoja, claro que eu lembro, desculpa, mas só vi seu comentário agora…
Você quer popular seu form a partir dos atributos de um bpm object? Precisa ser assíncrono?
Fala cara, valeu pela resposta :)
Não precisa ser assincrono não. É possível invocar um bpm method via submit do form de uma jsp?
Por quê você não passa seu BPMObject para sua view (JSP) e usa o valor dos seus atributos para pré-popular os campos? Não é disso que você precisa?
Pois é, o problema é que no meu caso, isso não acontece previamente.
Após o form renderizar, eu tenho a opção de usar um filtro que, submetendo este valor, alguns campos do form seriam carregados posteriormente, com dados referentes a esse filtro.
Mas se você submita o seu form, ele vai do lado servidor e com isso você consegue atualizar o seu BPMObject e jogar os valores atualizados novamente na JSP, não??
Pense nisso aí como MVC, O JSP é sua View, o seu screenflow o Controller e o BPMObject o Model.
Ah sim, mas sendo assim, eu teria que adaptar o meu screenflow pra me retornar o bpmobject corretamente, certo?
Porque a minha ideia era não precisar mexer no screenflow, pra ficar plugável, caso eu precise voltar a usar presentation aí não teria problema. Por isso recorri ao uso do ajax com as tags do Fuego.
Usando presentation ou não, o processo é o mesmo. Pelo menos deveria :)
Pois é… mas na jsp eu tenho uma propriedade chamada selectedButton que recupera a ação que o usuário requisitou, e segue a transição correspondente, já na jsp eu não tenho isso. Ou seja, preciso mudar meu argument mapping da atividade pra não dar problema, e de algum jeito, mandar pro flow a ação realizada.
O processo é o mesmo, o que muda é a forma como as informações são passadas. Por exemplo, na presentation o meu problema se resolve invocando um bpmobject no click do meu botão de filtrar. Ele resolve internamente, inclusive de forma assíncrona. Eu não consigo fazer o mesmo usando JSP, pelo menos não de maneira trivial.
Eu não consigo submeter um form invocando um bpm object (Pelo menos ainda não descobri como), por isso achei que houvesse a necessidade de mudar o screenflow (Adicionar uma nova transição, relacionada ao filtro).
Cara, posso estar viajando, ainda não conheço bem a plataforma de BPM, são muitas e muitas dúvidas… rs… Mas essa em especial tá dando dor de cabeça até hoje.
Eu fiz um paliativo, serializando meu bpmObject em XML e colocando no meu output, aí recupero usando javascript, mas acredito que deva ter um jeito mais “elegante” de se resolver.
Só me corrigindo logo no início da frase no último comentário.
“…Pois é… mas na “”Presentation”" eu tenho uma propriedade chamada selectedButton…”
Você nunca terá o poder e a liberdade do que programando Java web com Servlets, Struts, etc.. sempre vai ter uma trava, mas o lance é que muita gente usa o BPMS como uma maneira de construir software, quando na verdade não deveria.
Quanto ao seu problema, só vendo mesmo cara, tem coisas nesse BPMS da Oracle que são bem específicas e que as vezes é necessário dar uma volta mesmo.
Marcus… apenas aproveitando a deixa de seu comentário, concordo plenamente, muitas pessoas usam o ALBPM/Oracle BPM para construir softwares com caracteristicas que fogem do BPM. Já vi vários clientes com problemas por esse motivo.
Acredito que com a versão 11g esses tipo de coiso seja mais raro, porem a versão ainda está muito ruim.
Abraço
Wendell Gouveia
http://blog.pop.com.br/bpm/
Bom, de qualquer maneira, foi boa a troca de ideia, de fato ainda tem muita coisa que preciso aprender dessa plataforma.
Quanto ao 11g, eu ouvi dizer que viria com suporte nativo a ADF, pra JSF, então imaginei que a ideia fosse facilitar a construção de views. A ideia não é fugir do propósito do BPM, mas criar uma interface amigável (qualquer coisa é mais amigável que as presentations do BPMS).
Bom pessoal, aproveitando a data que nos encontramos, quero desejar um feliz ano novo pra vocês :)
Abração!
Eu li coisas sobre o 11g mas não o usei ainda.. já tem no site da Oracle? Uma das coisas que eu tinha lido, é que tudo pode ser feito por interface web.
Alguum de vocẽs tem algum paper com as diferenças entre as versões?
Vou dar uma catada nisso depois, mas se alguém tiver algum material para adiantar, pode ficar a vontade :)
Pantoja, abraço para você e sua família tb. Mande um abraço pro Franklin tb!