Criar um aplicativo BPM remoto com a integração do IBM Worklight e do IBM Business Process Manager

Este artigo descreve como integrar o IBM® Worklight® e o IBM Business Process Manager V8.0.1 Standard (IBM BPM) alavancando os APIs IBM BPM REST. Ao combinar o ambiente de desenvolvimento eficiente do IBM Worklight com a simplicidade dos APIs IBM BPM REST, os desenvolvedores de BPM podem entregar aplicativos móveis aos usuários de BPM rapidamente.

Gianpaolo Gabutti, Senior IT Specialist, IBM

Gianpaolo GabuttiGianpaolo Gabutti é IT Specialist senior na Itália, onde trabalha como consultor de gerenciamento de processos de negócios no IBM Software Services for WebSphere. Ele trabalha no setor de TI desde 1988 e possui experiência em diferentes tecnologias, como programação orientada a objetos, Enterprise Application Integration, J2EE e Eclipse. É formado em Economia pela Universidade Católica de Milão.



Luciano Raso, Senior IT Architect, IBM

Luciano RasoLuciano Raso é IT Architect na IBM Itália. Na IBM desde 1989, ele trabalhou como IT Architect com diferentes tecnologias, primeiros com as relacionadas a sistemas distribuídos e, depois, aos sistemas JEE. Em 2010, ele passou a fazer parte do Software Group como vendedor técnico e especialista de soluções nas áreas de gerenciamento de processos de negócios (BPM) e operational decision management (ODM). É formado em Engenharia eletrônica.



Tony Pigram, Solution Architect, IBM

Tony Pigram photoTony Pigram é Solution Architect na IBM com mais de 20 anos de experiência em uma ampla variedade de tecnologias. Durante sete desses anos, ele trabalhou como consultor no setor de aplicativos remotos. Atualmente, ele trabalha no portfólio de Processos mais inteligentes.



01/Nov/2013

Introdução

Este artigo descreve os diversos componentes de um aplicativo remoto IBM Worklight simples que interage com os processos de BPM por meio de chamadas API REST. Ele mostra todos os componentes necessários para a criação de um aplicativo remoto Worklight (em um ambiente ™ Android) que permite que os usuários de BPM autorizados ativem, trabalhem e realizem tarefas de processos em seus dispositivos móveis.

Este artigo é voltado, principalmente, para os desenvolvedores de BPM que desejam entender melhor como aprimorar suas soluções de BPM com recursos remotos ou precisam melhorar rapidamente o entendimento sobre as possibilidades oferecidas pela interação dos dois produtos. O foco do artigo é nos desenvolvimentos práticos, não na infraestrutura.

Por todos os motivos mencionados acima, e do ponto de vista da arquitetura, decidimos por uma abordagem simples. Desenvolvemos nossa solução no ambiente mais básico e simples, composto por um servidor IBM BPM independente (IBM BPM Express V8.0.1) e o IBM Worklight Developer Edition V5.0.6, porque ele deve ser mais acessível à maior parte dos leitores. Essa arquitetura simplificada tem a vantagem de ser instalável em uma máquina única (o laptop do leitor, por exemplo) e, por isso, pode ser utilizada como ambiente de autoestudo por desenvolvedores individuais que queiram testar o conceito e melhorá-lo enquanto experimentam e aprendem mais.

Nós assumimos que o leitor possui um conhecimento básico de desenvolvimento Java, JavaScript®, jQuery e BPM, mesmo assim, tentamos evitar qualquer possível complexidade que dificultaria a leitura desse artigo para desenvolvedores inexperientes.

O código de amostra está incluído para que seja possível ajustar e testar o cenário por conta própria (e fazer melhorias). Essa solução é uma amostra dos recursos e só deve ser usada como um exercício de aprendizagem em um ambiente de desenvolvimento ou teste para objetivos de autoestudo e educação.

Pré-requisitos

O pacote do processo é composto por um aplicativo de processos BPM de amostra chamar Car Tyres Order Placement, ou CTOP, desenvolvido com o IBM BPM Express V8.0.1 e disponível no arquivo CarTyresOrderPlacement.twx.

O pacote remoto é composto por um projeto IBM Worklight, CarTyresOrderPlacementProject, desenvolvido com o IBM Worklight Developer V5.0.6 em uma instalação Eclipse Juno 4.2 SR2. O pacote está disponível no arquivo CarTyresOrderPlacementProject.zip

Usamos o sistema operacional Microsoft® Windows® 7 com o kit de desenvolvimento do Java® versão 7 atualização 13.

Enquanto escrevíamos esse artigo, a IBM lançou uma nova versão do IBM Worklight (V6.0). Testamos o projeto Worklight no novo release e não encontramos nenhum problema para migrar o u executar os artefatos (adaptadores e aplicativos). Portanto, é possível decidir qual versão do Worklight usar. Observe que a única versão do Eclipse suportada pelo Worklight V6.0 é o pacote Eclipse Juno 4.2 SR2.

A IBM também lançou uma nova versão do IBM BPM (V8.5). Também fizemos testes nesse novo release e não encontramos problemas aparentes. No entanto, tenha em mente que desenvolvemos e testamos essa amostra em um ambiente BPM V8.0.1.

Para configurar seu ambiente IBM Worklight, siga as instruções a seguir no IBM Worklight: introdução. Nós acreditamos que você esteja familiarizado com esses documentos e que seguiu as instruções.

É possível importar o projeto de amostra do IBM Worklight no ambiente de trabalho do Eclipse da mesma forma que qualquer outro projeto Eclipse. No entanto, é necessário instalar o plug-in do IBM Worklight previamente, como ensina o link abaixo.

Para importar a amostra, faça o download , descompacte o arquivo na unidade de disco rígido e use a opção Eclipse padrão Import => Existing project into workspace.

Para visualizar o processo BPM de amostra, é necessário importar o arquivo .twx fornecido no ambiente do BPM. Não é necessário, mas é possível criar usuários no servidor do BPM Process Center(o repositório do usuário criado pelo aplicativo do processo). Acreditamos que você saiba criar usuários internos do BPM usando o Process Admin Console. Se não souber, consulte a documentação do produto.


Visão geral do IBM Worklight

O Worklight as organizações a ampliarem seus negócios para dispositivos móveis. Ele oferece uma plataforma de aplicativos remotos aberta, abrangente e avançada para desenvolver, executar e gerenciar esses aplicativos. Com o Worklight, é possível desenvolver, executar e gerenciar aplicativos HTML5, híbridos e nativos de forma eficiente, além de reduzir o custo de desenvolvimento, melhorar o prazo de lançamento no mercado e aprimorar o controle e a segurança de aplicativos móveis. O IBM Worklight usa tecnologias com base em padrões para evitar a conversão de código, os intérpretes proprietários e as linguagens de script impopulares.

Um bom ponto de partida para compreender o IBM Worklight é IBM Worklight: introdução. Apresenta vídeos, demos, informações de como fazer e outros materiais para ajudá-lo a compreender completamente o Worklight. Também é possível acompanhar a comunidade de suporte do Worklight Developer Edition em estouro da capacidade para fazer perguntas e encontrar as respostas sobre obtenção, instalação e uso do Worklight.


Configurando o ambiente

Depois de instalar e configurar os ambientes do IBM Worklight e do IBM BPM com sucesso, é necessário importar o processo de amostra. Abra o IBM BPM Process Designer e importe o aplicativo de processo chamado Car Tyre Order Placement (CTOP), no arquivo CarTyresOrderPlacement.twx, que está incluído no pacote de amostra baixado .

Testar o processo de amostra

Depois de importar o aplicativo de processo, abra-o no Process Designer e abra o BPD chamado Car Tyres Order Placement. Clique em Run para executar uma nova instância de processo. Alterne para a visualização do Process Inspector e verifique se o processo de amostra está funcionando conforme esperado.

Configurar o IBM Worklight

Descompacte o arquivo CarTyresOrderPlacementProject.zip na unidade de disco rígido. Abra o Eclipse IDE e importe o projeto selecionando File => Import e, em seguida, selecione Existing project into workspacen, conforme mostrado em .

Importar o projetoWorklight project no Eclipse

Se estiver usando o Worklight V6.0, o sistema reconhecerá que o projeto deve ser atualizado e iniciará um procedimento automático de migração.

Para essa amostra, usamos o Android como plataforma de destino para dispositivos móveis, mas é possível escolher um sistema operacional de ambiente cliente diferente do nosso. É possível adicionar mais ambientes ao projeto depois de testar e verificar se a versão Android está funcionando corretamente.

Depois de concluir a importação do projeto, navegue até o servidor/diretório de conf. do projeto e abra o arquivo worklight.properties. Será necessário modificar a última seção do arquivo para ser compatível com as configurações do ambiente do BPM, como mostra o fragmento de código abaixo.

########################################
#    Car Tyres Order Placement         #
########################################
bpm.admin.user=admin
bpm.admin.password=admin
bpm.hostname=192.168.201.169
bpm.port=9080

em que:

  • bpm.hostname é o nome do host do BPM que responde às chamadas REST
  • bpm.port é o número da porta do BPM para a s chamadas REST (o valor padrão é 9080).

    Não deixe rastreios de espaço em branco no elemento bpm.port para não ver uma mensagem de erro no console do Worklight ao implementar os adaptadores no servidor:

    [2013-07-01 10:10:04]    Adapter deployment failed
    [2013-07-01 10:10:04]    Element <port> must be a number.

Visão geral do processo de amostra

Para demonstrar como integrar o Worklight e o IBM BPM, criamos uma cenário de negócios simples para uma empresa fictícia chamada FooTyres.com. Nos cenários, a FooTyres.com é uma empresa revendedora. Os agentes de vendas da FooTyres.com visitam os clientes (revendedores, reparadores de pneus, mecânicos e outros) com frequência e coletam pedidos durante essas visitas. Em alguns casos, os pedidos são feitos por um agente de vendas após uma conversa por telefone com os clientes.

O agente de vendas inicia o processo preenchendo os detalhes do pedido, (como as características do pneu, a quantidade, o desconto proposto) e o sistema calcula o preço total para o pedido. Depois que o agente de vendas completar os detalhes restantes, (como endereço de entrega e prazo final), e o cliente estiver satisfeito com o preço calculado, o agente pode enviar o pedido para aprovação. Se o preço total ou o desconto do pedido forem maiores que o limite estabelecido (em nossa amostra, esses limites foram defini dos em 5.000 para o preço total e 8% para o desconto), o pedido deve ser aprovado por um gerente de vendas. Se o preço total ou o desconto forem menores que o limite, o pedido não precisa de aprovação e vai diretamente para o depósito para envio (o pedido é aprovado automaticamente).

O gerente de vendas pode rejeitar o pedido por razões comerciais (por exemplo, se considerar o desconto muito grande ou o preço total excessivo para aquele cliente específico). Nesses casos, o gerente de vendas deve explicar o motivo da rejeição, e o pedido voltará para o responsável pela venda. Então, o responsável pela venda deve decidir se cancela o pedido ou envia novamente para aprovação, geralmente depois de fazer uma atualização. Se o gerente de vendas aprovar o pedido, ele é enviado para o depósito para cumprimento.

O gerente de depósito também pode retornar o pedido ao agente de vendas, mas nesse caso, o motivo está relacionado a problemas logísticos. Por exemplo, se o pneu em questão estiver em falta no estoque ou se não for possível organizar o envio até a data esperada. Da mesma forma, os gerentes de vendas podem notificar o agente de vendas sobre os motivos da recusa para processar o pedido. Se o pedido voltar para o agente de vendas, é possível atualizar os detalhes (alterando, por exemplo, a data de entrega esperada) e enviá-lo novamente ou cancelá-lo.

Depois que o pedido for aprovado pelos gerentes de depósito, o envio é organiza do e o processo é concluído. Nesse momento, o processo pode ser estendido para notificar um sistema de contabilidade externo, mas isso não foi incluído em nossa amostra.

O cenário de negócios é ilustrado na definição de processo de negócios (BPD), mostra a Figura 2. .

O processo de amostra

Uma síntese do cenário

Para entender melhor o que faz cada arquivo ou código, vamos acompanhar um cenário de um aplicativo remoto e indicar qual código relacionado é responsável pela funcionalidade. Para testar o aplicativo, usaremos o emulador Android v4.0.3.

Na página inicial do dispositivo, selecione a visualização dos aplicativos instalados e clique no ícone CarTyresOrderPlacement , como mostra a Figura 3..

Iniciar o aplicativo

Isso inicia o aplicativo e exibe a tela inicial. Se o usuário não estiver logado, verá uma tela simples que exibe dois botões: Get Task List e Logout.

Clicar em Get Task List chama a interação de desafio (explicada com mais detalhes em ). Se o usuário não estiver logado, é solicitado que insira um nome de usuário e uma senha e clique em Submit, o que chama novamente a interação de desafio. O adaptador de autenticação é chamado, é feita uma tentativa de login.

Se houver falha (por exemplo, o usuário esquecer-se de mudar o endereço IP do servidor BPM), a mensagem de erro na Figura 4 é exibida.

Mensagem de erro de autenticação

Como é possível ver, o endereço IP definido no arquivo worklight.properties indica 192.168.201.169. Isso está incorreto, o que gera uma exceção. O log do console do Worklight também exibe a mensagem mostrada na Figura 5. .

Saída de console do Worklight

Como é possível ver, a mensagem é um pouco mais detalhada. É necessário abrir o arquivo worklight.properties e modificar seu ponto para a localização correta do servidor do BPM, como mostra o fragmento de código abaixo.

#############################################################
#    Car Tyres Order Placement
#############################################################
bpm.admin.user=admin
bpm.admin.password=admin
bpm.hostname=192.168.201.172
bpm.port=9083

Depois de atualizar, será necessário criar e implementar novamente o aplicativo no ambiente do Android. Depois de fazer o download e reinstalar o aplicativo no dispositivo, é possível fazer o login como antes. Depois de autenticar, será exibida uma lista de tarefas do BPM Task list associada ao usuário (você).

Buscar e renderizar a lista de tarefas

Como mencionado, clicar em Get Task List" chama a interação do desafio. Isso é feito internamento pelo Worklight, pois declaramos esse método como "protected" no arquivo authenticationConfig.xml.

Depois de concluir o desafio, a lista de tarefas do BPM é enviada ao aplicativo cliente para ser processada e renderizada para a interface com o usuário. Isso é o que acontece na função de retorno de chamada: function getTaskListOK(response) O propósito dessa função é receber os dados retornados pelo adaptador e criar dinamicamente o conteúdo que deve ser liberado pela tag <div> chamada responseDiv.

É possível clicar em uma tarefa listada para abri-la, como mostra a Figura 6. .

Tela da lista de tarefas

Observe que o manipulador click anexado a cada linha (da classe taskRow) representa uma tarefa disponível, como mostra o fragmento abaixo.

$('tr.taskRow').click(function() {
	var idx = $('tr').index(this);
	showOrder(myTaskData[idx-1].instanceId, myTaskData[idx-1].taskId);
});

Esse fragmento de JavaScript chama a função showOrder() quando um usuário clica na tarefa. A função é passada para os IDs da instância e da tarefa.

Se clicar na primeira linha na Figura 6, a tela mostrada na Figura 7 é exibida. .

Detalhes de pedido existente

A tela indica que esse pedido foi enviado anteriormente e aprovado automaticamente. Os campos estão em modo somente leitura, exceto Notes , que pode ser modificado se houver instruções futuras para o gerenciador de remessas.

Se você clicar no botão Get Task List , retorna à tela de lista de tarefas inicial.

Para criar um Novo pedido no dispositivo móvel, clique no botão New Order . Uma tela de novo pedido é exibida, como mostra a Figura 8. .

Novo pedido

Os valores para as caixas de seleção suspensas estão localizados no arquivo UIMaterial.js. Para esta amostra, esses valores eram codificados permanentemente, pois é pouco provável que eles mudem, se houver alteração. O HTML real para as telas também é codificado permanentemente no arquivo UIMaterial.js. De acordo com a tela sendo renderizada, uma chamada é feita para a função apropriada, e uma resposta de cadeia de caractere é retornada. Por sua vez, isso é retornado e renderizado na tag responseDiv div . Em seguida, está a função que retorna o código para renderizar a tela New Order.

//Get the layout for placing a new order or updating an existing one
	(most of the data can be entered / updated)
	function getNewOrderLayout() {
	
		return '<div class="box" id="message"></div>' +
			'<select id="widthSelect"></select><select id="profileSelect"
				style="float: right;"></select>
			<br><br>'+
			'<select id="rimSizeSelect"></select>
			<select id="quantitySelect" style="float: right;"></select>
			<br><br>'+
			'<label id="unitPriceLabel" for="unitPriceOutput" style="float: left;
				">Unit Price : </label>
			<label  isNumeric="true" baseType="Decimal" id="unitPriceOutput"
				style="font-weight : bold; ">0</label>'+
			'<span style="float: right;margin-right:10px">
			<label class="" id="totalPriceLabel" for="totalPriceOutput"
				>Total Price : </label>
			<label isNumeric="true" baseType="Decimal" id="totalPriceOutput"
				style="font-weight : bold;" >0</label>
			</span><br><br>'+
			'<select id="discountSelect"></select>
			<input type="button" value="Calculate Price" onclick="calculatePrice()"
				class="formButton" style="float: right;" />
			<br><br>'+
			'<table width="100%">'+
			'<tr>
			<td><label class="" id="nameLabel" for="nameInput"
				>Name :  </label></td>
			<td colspan="2"><input id="nameInput" type="text" value=""
				initialValue="" style="width: 100%; float: right;" /></td>
			</tr>'+
			'<tr><td><label class="" id="streetLabel" for="streetInput"
				>Street : </label></td>
			<td colspan="2"><input id="streetInput" type="text" value=""
				initialValue="" style="width: 100%;float: right;"/></td>
			</tr>'+
			'<tr>
			<td><label class="" id="cityLabel" for="cityInput"
				>City : </label></td>
			<td colspan="2"><input id="cityInput" type="text" value=""
				initialValue="" style="width: 100%;float: right;" /></td>
			</tr>'+
			'<tr>
			<td><label class="" id="datePickerLabel" for="datePicker"
				>Shipment Date : </label></td>
			<td><input id="datePicker" type="text"
				style="width: 100%;float: right;" />
			</td>
			</tr>'+
			'</table><br><br>'+
			'<label class="" id="notesLabel" for="noteInput"
				>Notes : </label>
			<textarea  id="notesInput" rows="2"
				style="width: 80%;float: right;"></textarea>
			<br><br>';
			
	}

Esta função pode parecer estranha em um primeiro momento, mas ela simplesmente retorna uma cadeia de caractere que declara o conteúdo de um elemento HTML div . O div é manipulado posteriormente por algum código jQuery, como mostraremos na seção . O usuário pode selecionar os valores das caixa de seleção, como mostra a Figura 9 .

Seleção suspensa do dispositivo

Em um navegador da web, a caixa de seleção suspensa só deve ser exibida na página se o usuário selecionar um valor com o teclado ou um clique do mouse. Entretanto, como esse aplicativo é executa em um dispositivo móvel, usa-se o método nativo de renderizar uma seleção suspensa. O usuário pode deslizar os dedos para cima ou para baixo para navegar pelos itens da lista. A interface com o usuário funciona da mesma forma para os campos Profile, Rim Size, Quantity e Discount .

Depois de selecionar os campos, o usuário pode pressionar o botão Calculate Price , como mostra a Figura 10, para calcular a Unidade e o Preço total com base em qualquer valor Discount selecionado.

Controle JQuery datePicker

Depois, o usuário pode inserir o texto para Name, Street e City. Como se trata de um aplicativo móvel, a entrada de texto deve ser mantida em um mínimo para evitar erros de digitação.

Quando o usuário clica no campo Shipment Date , o jQuery datePicker é exibido, como mostra a Figura 10. Ele pode rolar por um calendário para selecionar uma data futura.

O código para incluir o datePicker na tela está localizado em três arquivos: UIMaterial.js, CarTyresOrderPlacement.js e CarTyresOrderPlacement.html. Como mencionado antes, o arquivo UIMaterial.js retorna o HTML para renderizar a saída para a tela. O fragmento a seguir mostra onde o datePicker é definido.

<input id="datePicker" type="text" style="width: 100%;float: right;" />

No arquivo CarTyresOrderPlacement.js file, uma função de inicialização é chamada ao exibir a tela New Order. Isso inicia o datePicker e define o formato de data correto. Como o campo de entrada tem um ID do datePicker, detecta-se que ele requer o calendário pop-up seja chamado, como mostrado abaixo.

function initNewOrderLayout() {

	$('#ResponseDiv').html(getNewOrderLayout());
	$('#message').hide(); // Hide the message box
	$('#message').click(function() {

		$('.box').animate({
			opacity : 'toggle',
			height : 'toggle'
		});
	});
	//Init the date picker with the proper format...
	$( "#datePicker" ).datepicker({ dateFormat: "dd-mm-yy" });
	
	addOptions('#widthSelect', widthOptions);
	addOptions('#profileSelect', profileOptions);
	addOptions('#rimSizeSelect', rimSizeOptions);
	addOptions('#quantitySelect', quantityOptions);
	addOptions('#discountSelect', discountOptions);
}

Por fim, o arquivo CarTyresOrderPlacement.html os arquivos include necessários para o JQuery DatePicker, como mostra o fragmento abaixo.

	<!-- jquery for custom datePicker -->
	<link rel="stylesheet"    
    href="http://code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css" />
	<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
	<script src="http://code.jquery.com/ui/1.10.3/jquery-ui.js"></script>
	<!-- jquery for custom datePicker -->

Confira o webiste do jQuery datepicker para obter mais informações sobre ele.

Enviar o novo pedido

Depois que o usuário terminar de inserir os detalhes, pode pressionar Submit Order, conforme mostrado na Figura 11 .

Enviar um novo pedido

Os detalhes do novo pedido são enviado de volta para a função newOrder() (contida no arquivo CarTyresPlacement.js). Como mostra o fragmento abaixo, essa função depois chama a função startProcess() , no arquivo CarTyresOrderPlacementSOAPAdapter-impl.js. A função startProcess() cria uma mensagem SOAP que contém os dados do novo pedido e faz uma chamada SOAP para o servidor BPM.

Observe que as outras interações, como getOrderDetails, getTaskList e CompleteOrder uma o API REST.

function newOrder() {

	initNewOrderLayout();

	$('#newOrder').hide(); // Hide new order button
	$('#submitOrder').show(); // Show submit order button
	$('#complete').hide();// Hide complete button
	$('#header').html("New order submission");
	$('#submitOrder').click(function() {
		hideMessage();

		var myOrder = checkOrder();
		// WL.Logger.debug(JSON.stringify(myOrder));

		if (myOrder != null) {
			var invocationData = {
				adapter : "CarTyresOrderPlacementSOAPAdapter",
				procedure : "startProcess",
				parameters : [ myOrder ]
			};
			var options = {
				onSuccess : newOrderOK,
				onFailure : newOrderFAIL
			};
	
			WL.Client.invokeProcedure(invocationData, options);
		}

	});
}

Depois de fazer o envio com sucesso, o usuário recebe a mensagem exibida na Figura 12 .

Novo pedido bem-sucedido

Se, por algum motivo, o envio do pedido falhar, o usuário é informado por esse mesmo mecanismo. É possível usar o Process Designer para verificar se o novo pedido realmente foi enviado. Carregue o processo Car Tyres Order Placement e clique na visualização Process Inspector, como mostra a Figura 13. .

Visualização do Process Inspector

Aqui, é possível ver a criação de uma nova instância de processo. Também vemos que o token do processo foi motivo para a etapa Approval. usando o recurso de depuração à direita, é possível clicar duas vezes na variável order e visualizar os conteúdos para verificar se os dados inseridos na tela New Order do dispositivo móvel foram passadas com sucesso para essa nova instância de processo.

Agora, ao voltar para a tela Task List do dispositivo móvel, mostrada na Figura 14, será exibida a nova tarefa na lista. O indicador terá uma cor diferente, o que mostra que a tarefa precisa de aprovação.

Lista de tarefas mostrando nova tarefa

Observação: como estamos logados como administradores nessa amostra, podemos ver todas as tarefas associadas ao processo de amostra. Se você estava logado como um usuário não administrador, poderá ver apenas as tarefas pertencentes ao seu usuário. Como esse é um artigo de desenvolvedor, queremos mostrar tudo, mas lembre-se de que ao executar essa amostra com uma conta de usuário real atribuída às raias e atividades, as tarefas não pertencentes a você não serão mostradas na tela Task List.

Se clicar na última tarefa da lista, (o novo pedido aguardando aprovação), é possível verificar se os dados estão corretos, como mostra .

Exibir os detalhes da tarefa

A tela em é criada dinamicamente a partir da função getApproveOrderLayout() , no arquivo UIMaterial.js. Os detalhes reais do pedido são recuperados ao chamar a função getOrderDetails() , no arquivo CarTyresOrderPlacement.js, como mostrado abaixo.

function getOrderDetails(taskId,callBack) {

	var order = null;
	var invocationData = {
		adapter : "CarTyresOrderPlacementRestAdapter",
		procedure : "getOrderDetailByTaskId",
		parameters : [ taskId ]
	};

	WL.Client.invokeProcedure(invocationData,
					{
						onSuccess : function(response) {
    [...]

Por sua vez, isso chama a função getOrderDetailByTaskId() do adaptador API REST, no arquivo CarTyresOrderPlacementRestAdapter-impl.js, como mostrado abaixo.

function getOrderDetailByTaskId(taskId){
	
	path = 'rest/bpm/wle/v1/task/'+taskId+'?parts=all';
	
	var input = {
	    method : 'get',
	    returnedContentType : 'json',
	    path : path
	};
	
	response=WL.Server.invokeHttp(input);
	WL.Logger.debug(JSON.stringify(response));
	return response;
}

Log out

Em qualquer outra tela, o usuário pode clicar em Logout para cancelar a autenticação de sessão atual. Se o usuário selecionar Get Task List depois disso, ele terá que inserir o nome de usuário e a senha novamente para autenticar outra vez.

Aprovar um pedido

O cenário de aprovação ocorre quando um pedido precisa de aprovação dos gerentes ou do depósito. Neste cenário, a maior parte dos dados apresentados é de rótulos, porque eles não podem ser modificados pelos aprovadores, exceto o campo Notes , no qual os aprovadores devem inserir o motivo de recusa da aprovação antes de enviar o pedido de volta para o agente de vendas, e as caixas de seleção Approved e Shipped .

Atualizar um pedido existente

Este cenário ocorre quando um pedido foi enviado de volta para os agentes de vendas pelos gerentes ou o depósito. Nesse caso, a interface com o usuário é semelhante àquela do cenário Enviar novo pedido. No entanto, nesse caso, os dados já estão preenchido e prontos para serem modificados.


Desenvolvimento do lado do servidor

Para informações sobre a função dos adaptadores no Worklight, as tipologias diferentes e como configurá-los, consulte os documentos de desenvolvimento do lado do servidor do developerWorks Worklight.

Nossa amostra exibe o uso de adaptadores HTTP em dois tipos diferentes: um adaptador SOAP/HTTP (o adaptador que iniciar o processo) e um adaptador REST (para conduzir todas as outras interações com o servidor BPM)

Implementar a autenticação

Em um ambiente de produção real, a autenticação será manipulada de forma diferente que no aplicativo de amostra. Mesmo assim, acreditamos que há vantagens em desenvolver um mecanismo de autenticação simplificado ad hoc, mesmo para um ambiente básico como o nosso, porque:

  • Ele ajuda a compreender o funcionamento da autenticação e do mecanismo de autorização disponível e simples de instalar com o IBM Worklight.
  • Ele pode ser usado em provas de conceito para simular o comportamento de tempo de execução para ambientes mais complexos.

É fornecida uma descrição geral detalhada de como a segurança é tratada pela plataforma IBM Worklight no developerWorks Worklight autenticação e segurança . Esses documentos fornecem instruções simples e claras sobre como criar adaptadores usando o assistente que acompanha o plug-in do Worklight.

Antes de discutir a implementação do adaptador de autenticação, queremos esclarecer alguns conceitos que consideramos importante compreender para prosseguir com o processo. Como descrito na documentação do IBM Worklight:

  • Um authenticator é uma entidade do lado do servidor responsável pela coleta das credenciais do aplicativo cliente (essa atividade também é chamada de "desafio").
  • Um login module é uma entidade do lado do servidor responsável por verificar as credenciais do usuário (e criar um objeto de identidade do usuário, que preserva as propriedades do usuário para o restante da sessão).
  • Um authentication realm define o processo que será usado para autenticar usuários.
    • Cada região de autenticação é composto por um autenticador e um módulo de login.
    • Cada região de autenticação requer um componente manipulador de desafios presente no lado do cliente.
  • Um security test é um conjunto solicitado de regiões de autenticação usado para proteger um recurso, como um procedimento do adaptador, um aplicativo ou uma URL estática.

Todas essas configurações definidas no arquivo server/conf/authenticationConfig.xml do projeto.

Com uma compreensão clara desses conceitos, vamos ver como fazer para proteger um recurso (no nosso caso, o recurso é representado por um procedimento adaptador).


Configuração do lado do servidor

As primeiras coisas para se configurar são os procedimento do adaptador, que devem ser protegidos. Na nossa amostra, protegemos o procedimento que disponibiliza as listas de tarefas para os usuários (o que é conhecido em um servidor do portal BPM como a visualização Task Inbox). O nome do procedimento é getTasksList() . Ele é implementado pelo adaptador CarTyresOrderPlacementRestAdapter. . É necessário adicionar a entrada a seguir no arquivo CarTyresOrderPlacementRestAdapter.xml.

<procedure name="getTaskList"
		securityTest="SimpleAuthAdapter-securityTest">
		<description>Gets the initial task list for the user</description>
</procedure>

Estamos afirmando aqui que o uso desse procedimento está sujeito a um teste de segurança chamado "SimpleAuthAdapter-securityTest".

A próxima etapa é a definição do teste de segurança: isso exige outra entrada no arquivo "server/conf/authenticationConfig.xml":

</securityTests>
	<customSecurityTest name="SimpleAuthAdapter-securityTest">
       	<test isInternalUserID="true" realm="CTOPAuthRealm"/>
	</customSecurityTest>  	
</securityTests>

Se os usuários internos estiverem na região de autenticação chamada CTOPAuthRealm, eles devem ser considerados autenticados.

A próxima etapa é a definição do domínio, que representa outra entrada no arquivo, como mostrado abaixo.

<realms>
   <realm name="CTOPAuthRealm" loginModule="SimpleAuthLoginModule">
      <className>com.worklight.integration.auth.AdapterAuthenticator</className>
      <parameter name="login-function" value="SimpleAuthAdapter.onAuthRequired"/>
      <parameter name="logout-function" value="SimpleAuthAdapter.onLogout"/>
   </realm>
</realms>

Como definido anteriormente, uma região de autenticação é feita a partir de um autenticador e um módulo de login. Por isso, nós declaramos aqui módulo de login usado por essa região e a implementação de classe para o autenticador. Também declaramos os métodos de retorno de chamada chamados pelo Worklight quando a autenticação é necessária ou o usuários faz logout.

A última etapa de configuração é definir o módulo de login. Para isso, adicione a entrada abaixo no arquivo server/conf/authenticationConfig.xml.

<loginModules>
	<loginModule name="SimpleAuthLoginModule">
	     <className>com.worklight.core.auth.ext.NonValidatingLoginModule</className>
	</loginModule>
<loginModules>

Aqui, nós escolhemos o NonValidatingLoginModule predefinido. Isso significa que nenhuma validação adicional é feita pelo Worklight, e o desenvolvedor deve se responsabilizar pela validação da credencial no adaptador (na nossa amostra, ela está contida em SimpleAuthAdapter).

Agora que as etapas de configuração da autenticação foram concluídas, é necessário implementar os componentes do JavaScript. Para isso, são necessários um manipulador de desafios do lado do cliente e um autenticador do lado do servidor.

Implementar o manipulador de desafios

O manipulador de desafios deve implementar dois métodos:

  • isCustomResponse(): essa função é chamada pelo Worklight cada vez que uma resposta é recebida do servidor. isso é usado para detectar se a resposta contém dados relacionados a esse manipulador de desafio e deve retornar true ou false.
  • handleChallenge(): se isCustomResponse retornar true, a estrutura chama a função handleChallenge() . Ela é usada para realizar ações obrigatórias (em nossa amostra, apresentamos ao usuário uma tela de login na qual ele pode inserir o nome de usuário e a senha. Depois de inserir esses valores, chamamos o procedimento de autenticação do adaptador usando o API submitAdapterAuthentication. Esse API manipulador de desafios é usado para enviar credenciais coletadas para um procedimento de adaptador específico.

    Na amostra fornecida, haverá a função a seguir para chamar:

    var invocationData = {
    	adapter : "SimpleAuthAdapter",
    	procedure : "submitAuthentication",
    	parameters : [ username, password ]
     };
    
     simpleAuthRealmChallengeHandler.submitAdapterAuthentication(invocationData, {});

Implementar a autenticação do lado do servidor

No lado do servidor, é necessário implementar o autenticador SimpleAuthAdapter. Para desenvolver o adaptador, descobrimos que um bom ponto de partida é o exemplo fornecido na apresentação IBM Worklight V5.0.6 Getting Started: Custom Authenticator and Login Module (PDF).

Durante o desafio, o aplicativo cliente chama submitAuthentication(username, password), por isso, é necessário criar uma função para manipulá-lo. Essa função deve retornar um objeto JSON para o cliente, declarando se a autenticação teve êxito ou não. O objeto retornado é da seguinte forma:

{
	authRequired: true,
	errorMessage: errorMessage,
	isSuccessful : false
}

Se for necessário autenticar o usuário (o teste de segurança não foi bem-sucedido) ou o teste de segurança passar, é retornado:

{
	authRequired: false
}

Ao examinar nossa amostra, observe que, para verificar se as credenciais são válidas, a função submitAuthentication() utiliza a função interna checkUser(user, password). Na nossa implementação, enviamos uma solicitação de post HTTP a um servidor BPM e verificamos se a resposta contém um LtpaToken. Se as credenciais forem válidas, os servidor retornará um cookie (LtpaToken2) para ser usado em solicitações subsequentes. Caso contrário, o cookie não estará presente na resposta. Na nossa amostra, não queremos armazenar o cookie, É necessário apenas verificar se ele existe.

A seguir, temos a implementação da função submitAuthentication() :

function submitAuthentication(username, password){

	var userDetails = checkUser(username,password);
	
	if (!userDetails.isSuccessful) { 		
		return onAuthRequired(null, userDetails.errors[0]);

	} elseif 
    (userDetails.data != undefined && userDetails.data != null  ){
		//Store user's data
		var userIdentity = {
				userId: username,
				displayName: userDetails.data.fullName,
				attributes: {
					memberships : userDetails.data.memberships
				}
		};

		WL.Server.setActiveUser("CTOPAuthRealm", userIdentity);
		
		return {
			authRequired: false 
		};
	}

Não adianta concluir a autenticação e configurar o usuário ativo em CTOPAuthRealm usando o API do servidor WL.Server.setActiveUser(). Isso evitará a falha de testes de segurança posteriores.

A segunda função que precisa ser implementada é a função protegida getTaskList(). Ela realiza uma consulta no servidor BPM usando o API REST e retorna uma lista de tarefas disponíveis para o usuário autenticado (a lista é representada por um array de objetos JSON). Essa solicitação é feita em nome do usuário, mas, dessa vez, o sistema utiliza o mecanismo de "autenticação simples" de HTTP, que será explicado mais detalhadamente.

Para confirmar o que acontece no tempo de execução, a seguir há uma sequência completa das etapas que ocorrem quando a função protegida é chamada:

  1. o cliente chama o procedimento protegido do adaptador (getTaskList()).
  2. O Worklight intercepta a solicitação e ativa o mecanismo de desafio. Se o teste de segurança não for cumprido, o manipulado r de desafios cliente recebe um retorno de chamada no método isCustomResponse , indicando que a autenticação foi solicitada.
  3. O cliente manipula o desafio chamando o procedimento submitAuthentication() do adaptador
  4. O cliente recebe uma segunda notificação e, agora, pode determinar se o procedimento de autenticação foi concluído com sucesso (o usuário está autenticado).
  5. Se o usuário estiver autenticado, o cliente informa ao servidor a intenção de conduzir o procedimento inicial de autenticação (isso é feito ao chamar o API manipulador de desafios submitSuccess()).
  6. O cliente recebe a resposta do chamado inicial para o procedimento protegido e renderiza o resultado.

Criar os adaptadores

Cada adaptador pode ser criado com o uso do assistente fornecido pelo ambiente de desenvolvimento do Worklight. Ao criar um novo adaptador, o assistente mostrado na Figura 16 é exibido. Nele, insere-se o nome e o tipo do adaptador.

Assistente do adaptador do Worklight

Isso crua uma posta com a estrutura mostrada na Figura 17 .

Estrutura de pasta dos adaptadores

<AdapterName>.xml é o descritor do adaptador e contém diversos parâmetros de configuração de adaptador. Se o tipo do adaptador for configurado como HTTP, é necessário inserir informações sobre o protocolo usado, o endereço do servidor e a porta usada para a conexão e o tipo de autenticação, como mostra a Figura 18. .

Política de conexão do descritor de adaptadores

O adaptador SOAP

Quando o usuário pressiona o botão Submit na tela New Order, cria-se uma nova instância de processo do processo de amostra do BPM Car Tyres Order Placement. A nova instância pode ser ativada com Start Event ( (WS Start) associada ao serviço da web, como mostra a Figura 19. .

O ponto de entrada do adaptador SOAP no processo

Essa tarefa é realizada pelo adaptador HTTP CarTyresOrderPlacementSOAPAdapter, que é definido pelo descritor a seguir:

<wl:adapter name="CarTyresOrderPlacementSOAPAdapter"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:wl="http://www.worklight.com/integration"
	xmlns:http="http://www.worklight.com/integration/http">

	<displayName>CarTyresOrderPlacementHTTPAdapter</displayName>
	<description>CarTyresOrderPlacementSoapAdapter</description>
	<connectivity>
		<connectionPolicy xsi:type="http:HTTPConnectionPolicyType">
			<protocol>http</protocol>
			<domain>${bpm.hostname}</domain>
			<port>${bpm.port}</port>	
			<authentication>
				<basic />
				<serverIdentity>
					<username>${bpm.admin.user}</username>
					<password>${bpm.admin.password}</password>
				</serverIdentity>
			</authentication>
		</connectionPolicy>
		<loadConstraints maxConcurrentConnectionsPerNode="2" />
	</connectivity>

	<procedure name="startProcess" securityTest="SimpleAuthAdapter-securityTest">
		<displayName>start process</displayName>
	</procedure>
</wl:adapter>

O adaptador contém apenas o procedimento exposto ao cliente: startProcess(order). Esse procedimento é configurado como protegido (da mesma forma que os outros procedimentos nessa amostra) por questões do teste de segurança SimpleAuthAdapter-securityTest descrito na seção anterior. Esse procedimento chama o serviço da web ao criar o envelope SOAP derivado do arquivo WSDL que descreve o serviço da web em si.

Em geral, ao chamar um serviço da web de uma classe Java, é possível usar uma das diversas estruturas disponíveis, como AXIS, que fornece assistentes para gerar as classes auxiliares e as principais necessárias para chamar o serviço da web. Essas classes auxiliares fornecem uma camada mais abstrata que ajuda os desenvolvedores a simplificarem uma chamada de serviço da web, ocultando a complexidade da serialização e desserialização do modelo de objeto usado para trocar dados entre o cliente e o serviço da web. Também é possível ocultar a complexidade da comunicação no protocolo HTTP.

Na nossa amostra, usamos o JavaScript para implementar o adaptador, não o Java. Por isso, não há estrutura ou assistente disponíveis para gerar a solicitação de serviço da web. Entretanto, um adaptador HTTP do Worklight HTTP simplifica a troca de dados com um sistema de backend por meio de um protocolo HTTP, pois exige apenas o envelope SOAP necessário para chamar o serviço da web.

Para criar o envelope, exploramos o esqueleto de envelope gerado pela ferramenta SoapUI de software livre, que auxilia com o teste e a análise de serviços da web. Dado um WSDL, o SoapUI pode gerar o modelo de envelope correspondente preenchido com os dados solicitado, como mostra a Figura 20. .

O envelope para iniciar o processo, como mostrado na interface com o usuário do SOAP

Cada um dos símbolos abaixo ? deve ser substituído pelo valor dos dados correto. Usando o fragmento a seguir, o adaptador pode mesclar o exemplo acima com os dados solicitados:

var request = '<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:star="http://CTOP/StartWS.tws">'
			+ '  <soapenv:Header/>'
			+ '  <soapenv:Body>'
			+ '     <star:createOrder>'
			+ '        <star:order>'
			+ '          <star:userId>'+user.userId+'</star:userId>'
			+ '          <star:quantity>'+order.quantity+'</star:quantity>'
			+ '          <star:width>'+order.width+'</star:width>'
			+ '           <star:profile>'+order.profile+'</star:profile>'
			+ '           <star:rimSize>'+order.rimSize+'</star:rimSize>'
			+ '           <star:unitPrice>'+order.unitPrice+'</star:unitPrice>'
			+ '           <star:discount>'+order.discount+'</star:discount>'
			+ '           <star:total>'+order.total+'</star:total>'
			+ '           <star:notes>'+order.notes+'</star:notes>'
			+ '            <star:dateRequired>'+order.dateRequired+'</star:dateRequired>'
			+ '           <star:shippingAddress>'
			+ '                 <star:name>'+order.shippingAddress.name+'</star:name>'
			+ '                 <star:street>'+order.shippingAddress.street+'</star:street>'
			+ '                 <star:city>'+order.shippingAddress.city+'</star:city>'
			+ '           </star:shippingAddress>'
			+ '           <star:approved>'+order.approved+'</star:approved>'
			+ '           <star:canceled>'+order.canceled+'</star:canceled>'
			+ '           <star:shipped>'+order.shipped+'</star:shipped>'
			+ '        </star:order>'
			+ '     </star:createOrder>'
			+ ' </soapenv:Body>'
			+ '</soapenv:Envelope>';

O fragmento a seguir obtém o envelope que será enviado para o BPM usando o API fornecido pelo Worklight:

var path = "teamworks/webservices/CTOP/StartWS.tws";var input = {
		method : 'post',
		returnedContentType : 'xml',
		path : path,
		headers : {
			'SOAPAction' : 'http://CTOP/StartWS.tws/createOrder'
		},
		body : {
			content : request,
			contentType : 'text/xml; charset=utf-8'
		}
	};
	response = WL.Server.invokeHttp(input);

No fragmento acima, não há evidências de terminal da web em serviço. Isso é calculado pelo Worklight, que concatena as informações no descritor do adaptador, como mostrado aqui:

<connectivity>
		<connectionPolicy xsi:type="http:HTTPConnectionPolicyType">
			<protocol>http</protocol>
			<domain>${bpm.hostname}</domain>
			<port>${bpm.port}</port>

O valor do caminho da variável é configurado como segue:

var path = "teamworks/webservices/CTOP/StartWS.tws";

Os APIs REST

O IBM BPM oferece um conjunto de APIs que são implementados usando serviços Representational State Transfer (REST). Um conjunto de REST relacionado à definição de processo de negócios (BPD) é fornecido para acessar o processo de negócios, as tarefas manuais e os dados de categoria de negócios. Esses APIs REST permitem que os desenvolvedores criem uma interface com o usuário ou customizem um aplicativo de portal existente. Os APIs são simples o suficiente para serem chamados por dispositivos móveis ou Rich Internet Applications (RIAs).

Para mais informações sobre como usar as APIs REST no IBM BPM, consulte o artigo do developerWorks Using the REST APIs in IBM Business Process Manager V7.5.

O adaptador REST

O adaptador REST CarTyresOrderPlacementRestAdapter contém todas as funções necessárias para chamar alguns dos serviços RESTFUL fornecidos pelo IBM BPM. Como o adaptador SOAP, o adaptador REST é HTTP. O API REST é chamado por meio do protocolo HTTP. O descritor do adaptador REST mostra que ele define e expõe para o cliente as três funções a seguir:

function getTaskList()
function getOrderDetailByTaskId(taskId)
function completeOrder(order)

É possível definir a política de conectividade no descritor, como mostra a Figura 21. Por isso, quando o API WL.Server.invokeHttp é chamado, não é necessário fornecer os detalhes de conectividade.

O editor do adaptador

A seguir, há uma breve descrição de cada uma das três funções definidas pelo adaptador REST:

Função getTaskList()
O objetivo dessa função é recuperar a lista de tarefas atribuídas ao usuário remoto atual ou ao grupo participante do qual o usuário faz parte. Para recuperar a lista de tarefas, o fragmento de código a seguir é usado:
function getTaskList() {
	var user = WL.Server.getActiveUser().userId;
	path =
'rest/bpm/wle/v1/search/query?condition=bpdName%7CCar%20Tyres%20Order%20Placement&
condition=taskStatus%7CReceived&organization=byInstance';
	var input = {
		method : 'put',
		returnedContentType : 'json',
		path : path
	};
	return filterTaskList(WL.Server.invokeHttp(input), user);
}

Como o mecanismo de autenticação se baseia nas informações codificadas permanentemente no descritor do adaptador, cada chamada para um serviço é feita usando o usuário "admin". Dessa forma, a lista de tarefas recuperada pode conter tarefas que não podem ser atribuídas ao usuário logado no aplicativo remoto. Por isso, a lista de tarefas deve ser filtrada para excluir essas tarefas e incluir apenas aquelas que pertencem ao usuário logado.

Para isso, em cada tarefa, a propriedade assignedTo é comparada à lista de grupos dos quais o usuários logado faz parte. Se a tarefa dor atribuída a um grupo do qual o usuário é membro, ela é deixada na lista. Caso contrário, ela é removida.

Clique aqui para ver lista de códigos

function filterTaskList(response, user) {
	var filteredTaskList = [];
	var data = response.data.data;
	var groups = getUserGroups(user);
	for ( var i = 0; i < data.length; i++) {
		var task = data[i];
		if (checkAssignement(task,user,groups)){ 			filteredTaskList[filteredTaskList.length]=task;
		}
	}
	response.data.data=filteredTaskList;
	return response;
}

Para recuperar a lista de grupos das quais o usuário faz parte, é possível usar a função a seguir:
function getUserGroups(user) {
	var groups = new Array(); 
var path = 'rest/bpm/wle/v1/users?filter='
			+ user
			+ '&includeTaskExperts=false&sort=true
                &includeInternalMemberships=true&parts=all';
	var input = {
		method : 'get',
		returnedContentType : 'json',
		path : path
	};
	response = WL.Server.invokeHttp(input);	
	if (response != null 
            && response.data.users.length > 0) {
		groups = response.data.users[0].memberships;
	}
	return groups;
}
Função getOrderDetailByTaskId(taskId)
Quando o usuário seleciona uma linha na lista de tarefas, os dados relacionados ao pedido correspondente são recuperado pela chamada dessa função. Nesse caso, os dados solicitados são recuperados com a chamada de um serviço RESTful fornecido pelo BPM. Essa função não apresenta nenhum problema específico, como é possível ver no código a seguir:
function getOrderDetailByTaskId(taskId) {
	path = 'rest/bpm/wle/v1/task/' + taskId + '?parts=all';
	var input = {
		method : 'get',
		returnedContentType : 'json',
		path : path
	};
	response = WL.Server.invokeHttp(input);
	return response;
}
Função completeOrder(order)
Quando o usuário cria ou aprova um novo pedido ou modifica um pedido recusado, é necessário pressionar o botão Submit para chamar a função.

Essa função chama um serviço RESTful e envia o pedido inserido pelo usuário por meio do aplicativo remoto. Esse comportamento seria o mesmo se o usuário trabalhasse no pedido em um coach de tarefa manual BPM tradicional. Como uma tarefa foi criada no BPM, seus dados são enviados para aquele serviço, e a tarefa é concluída. Quando isso ocorre, o processo avança para a próxima tarefa na lista.

O único aspecto a ser destacado nessa função é que o BPM espera a data no formato ISO 8601 (0000-00-00T00:00:00Z), mas quando o JavaScript converte o objeto de JSON para uma cadeia de caracteres, cada propriedade definida como uma data é convertida para o formato 0000-00-00T01:02:03.mmmmZ, o que provoca a falha da chamada REST. Nós encontramos uma solução alternativa o problema:

var orderToBeSent = JSON.stringify(bpmOrder).replace(/\.[0-9][0-9][0-9]Z/g,"Z");

Isso substitui cada data para o formato esperado pelo BPM. Há seguir está o código de função completo:

function completeOrder(order) {
	var bpmOrder = new BPMOrder(order);
	if (bpmOrder.userId == null || bpmOrder.userId == "")
		bpmOrder.userId = "admin";
	var orderToBeSent = JSON.stringify(bpmOrder).replace(/\.[0-9][0-9][0-9]Z/g,"Z");
// correct date format: millisec not accepted by bpm -> from
					// 0000-00-00T01:02:03.mmmmZ to 0000-00-00T01:02:03Z
	path = 'rest/bpm/wle/v1/task/' + order.taskId + '?action=finish&params='
			+ escape('{"order":' + orderToBeSent + '}') + '&parts=all';
	var input = {
		method : 'put',
		returnedContentType : 'json',
		path : path
	};
	response = WL.Server.invokeHttp(input);
	return response;
}

Client-side development

Embora haja diversas possibilidades para melhorar a interface com o usuário do cliente, decidimos mantê-la o mais simples e básica possível. A interface com o usuário pode ser melhorada de várias formas, mas isso deve ser feito depois que as partes da funcionalidade forem compreendidas, configuradas e implementadas. Nós baseamos a interface com o usuário deste artigo naquilo que está disponível e é simples de instalar no IBM Worklight: plataforma: jQuery.

Para mostrar como um plug-in jQuery plug-in pode ser usado de forma eficiente, substituímos o widget jQuery datepicker para selecionar as datas na interface com o usuário. O widget está disponível aqui.

Material do lado do cliente

O material do cliente é composto por um conjunto de arquivos JavaScript .js, um HTML, um .css e algumas imagens. Depois de importar o projeto no ambiente de trabalho, abra a perspectiva do Java EE e verifique se a visualização do Project Explorer é a mesma exibida . Os materiais do lado do cliente são descritos nessa seção.

A estrutura de pasta dos aplicativos

CarTyresOrderPlacement.html

Essa é a página HTML principal e não será alterada durante o tempo de vida de uma sessão do usuário. O HTML contém dois elementos HTML div elements (ResponseDiv e AuthDiv), que são manipulados pelas funções do jQuery quando a resposta for recebida pelo servidor do Worklight. Um exemplo de manipulação comum do DOM para alterar o conteúdo do div é representado pela função getTaskListOK(), a função de retorno de chamada que executa em uma chamada com êxito do procedimento do adaptador getTaskList() :

Clique aqui para ver lista de códigos

var myTaskData = response.invocationResult.data.data;	
	var tasks = null;
	if (myTaskData != null) {
		tasks = $.map(myTaskData, function(value, i) {
			
			var image= "'images/mblDomButtonOrangeBall.png'";
			if (value.taskSubject.indexOf("Approval") > 0)
				image= "'images/mblDomButtonRedBall.png'";
			elseif (value.taskSubject.indexOf("Shipment") > 0)
				image= "'images/mblDomButtonGreenBall.png'";
			
			return '<td><img src='+image+'
/></td><td><b>Order Number : </b>'
+ value.instanceId + '&nbsp;<b>Activity : </b>'+ value.taskSubject+'</td>';
		});
	}
	if (tasks == null || tasks.length == 0)
		$('#ResponseDiv').html('No orders found ');
	else
		$('#ResponseDiv').html( 				'<br/><table><tr class="taskRow">' +
tasks.join('</tr><tr class="taskRow" >')
+ '</tr></table>');

Como é possível notar o objeto JSON que declara a resposta é usado para criar um array válido dos elementos HTML td . Esses elementos são unificados para desenvolver uma tabela HTML, que pode ser usada para configurar o conteúdo do div (usando o jQuery html() ).

BO.js

Bo.js contém os objetos de negócios JavaScript usados no lado do cliente CarTyresOrderPlacement.js. Ele contém o código JavaScript principal para manipular as interações com o servidor do Worklight. Basicamente, dependendo do botão clicado pelo usuário, um adaptador é chamado, e uma resposta é recebida de volta como uma objeto JSON. Então, o código cria o conteúdo para ResponseDiv e anexa os manipuladores a diversos elementos para fornecer a sequência de eventos correta. O código é comentado para simplificar a compreensão de quais operações estão sendo executadas.

É possível executar as ferramentas de depuração comuns do JavaScript para depurar esse código como um recurso comum ou em um simulador de navegador remoto.

InitOptions.js

Esse arquivo é gerado automaticamente pelo assistente quando um novo projeto é gerado, e permanece quando intocado.

Messages.js

Esse arquivo também é gerado automaticamente pelo assistente quando um novo projeto é gerado. Seu propósito é fornecer um local para a internacionalização (i18n) das mensagens, que não consideramos na nossa amostra (ainda que seja algo normalmente necessário em um aplicativo do mundo real).

SimpleAuthRealmChallengeProcessor.js

Esse arquivo contém o código do cliente JavaScript para manipular o desafio, como descrito anteriormente neste artigo

UIMaterial.js

O arquivo contém algumas funções de utilitário para dar suporte à interface com o usuário.

CarTyresOrderPlacement.css

Este arquivo contém as declarações CSS comuns (ou seja, as definições CSS padrão). Essas declarações podem ser substituídas por outros arquivos CSS nivelados a diversos ambientes (como Android)


Conclusão

Neste artigo, nós fornecemos conceitos e códigos de amostra para ajudá-lo a ver os benefícios e as possibilidades de integração entre o IBM Worklight e o IBM BPM usando o API REST. Esperamos que você tenha visto como é simples fazer essa integração. Não é necessária nenhuma linha de código Java para desenvolver o aplicativo!


Próximas etapas

A seguir, há uma lista de aprimoramentos potenciais que podem ser realizados. São coisas que não tivemos tempo para concluir ou que gostaríamos de ter feito um pouco diferente:

  • Internacionalização
  • Realizar o push de notificações para usuário remotos quando ocorrerem eventos no lado do servidor
  • Melhorias da interface com o usuário (usando plug-ins jQuery adicionais)

Downloads

DescriçãoNomeTamanho
Sample applicationCarTyresOrderPlacement.twx1MB
Sample project fileCarTyresOrderPlacement.zip17MB

Recursos

Comentários

developerWorks: Conecte-se

Los campos obligatorios están marcados con un asterisco (*).


Precisa de um ID IBM?
Esqueceu seu ID IBM?


Esqueceu sua senha?
Alterar sua senha

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


A primeira vez que você entrar no developerWorks, um perfil é criado para você. Informações no seu perfil (seu nome, país / região, e nome da empresa) é apresentado ao público e vai acompanhar qualquer conteúdo que você postar, a menos que você opte por esconder o nome da empresa. Você pode atualizar sua conta IBM a qualquer momento.

Todas as informações enviadas são seguras.

Elija su nombre para mostrar



Ao se conectar ao developerWorks pela primeira vez, é criado um perfil para você e é necessário selecionar um nome de exibição. O nome de exibição acompanhará o conteúdo que você postar no developerWorks.

Escolha um nome de exibição de 3 - 31 caracteres. Seu nome de exibição deve ser exclusivo na comunidade do developerWorks e não deve ser o seu endereço de email por motivo de privacidade.

Los campos obligatorios están marcados con un asterisco (*).

(Escolha um nome de exibição de 3 - 31 caracteres.)

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


Todas as informações enviadas são seguras.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=80
Zone=Desenvolvimento móvel, WebSphere
ArticleID=951168
ArticleTitle=Criar um aplicativo BPM remoto com a integração do IBM Worklight e do IBM Business Process Manager
publish-date=11012013