Вы находитесь на странице: 1из 36

BSP + jQuery Mobile, ou a aventura de SAP-webdev parte

I: Preparao e login
FALAE SEUS BANDO DE CONSULTOR DEGENERADO! Tudo certo com vocs? Sim, eu estou de volta s agora em 2015 porque
finalmente eu tenho algum contedo bacana pra colocar aqui. Porm antes de comear a historinha do post, um breve:

Aviso! | Advertencia! | Warning! | Warnung!


Esta srie de posts, apesar de possuir contedo ABAP, est focada em interface web, portanto o leitor deve
esperar neste contedo referncias a assuntos como:

HTML5;

CSS;

JavaScript / jQuery;

e desenvolvimento web em geral.

Introduo
Recentemente, eu fui envolvido num projeto onde o cliente quer modernizar a interface de algumas transaes, que so
executadas atualmente via SAP Console. Essas transaes servem de suporte pra uma operao de coleta de materiais, e
devido essa natureza os operadores utilizam PDAs com Windows NT (sim, essas coisas ainda existem e esto sendo
usadas) que acessam o SAP. A ideia do projeto migrar as transaes pra aplicaes BSP e depois, aos poucos, substituir os
dispositivos que os operadores usam por outros mais novos, com sistemas mais modernos (Android ou iOS).
Mas por que usar BSP?, talvez seja a dvida que surja neste momento. Talvez, porque ao parar pra pensar, BSP a nica
alternativa vivel. A nica verso de WebDynpro que suporta integrao mvel a verso Java, e de conhecimento
comum que a performance de aplicaes WebDynpro muito inferior quando comparada performance de outras
tecnologias de interface web (esse post aqui, apesar da propaganda bvia, ilustra o problema), o que um ponto crucial
quando decidimos o que usar numa aplicao mvel. Por esse mesmo motivo, riscamos as transaes Easy Web da lista de
candidatos. No h a disponibilidade de usar Gateway, porque o ambiente no tem os componentes disponveis e s a
instalao e configurao dos mesmos daria um projeto parte. Portanto, devido flexibilidade necessria, nos resta
apenas o BSP pra fazer o backend. O framework do BSP praticamente o mesmo desde o R/3 4.7, o que facilita tanto o
entendimento para a construo como as manutenes posteriores.
Com o backend decidido, o que usar de frontend? Como a aplicao vai rodar em navegadores / dispositivos mais novos, no
faz sentido usar o ultrapassado HTMLB. Qual das trocentas alternativas de bibliotecas pra frontend a melhor? Essa deciso,
no meu caso, tambm j estava quase tomada o cliente j tinha algumas aplicaes BSP com interfaces implementadas
em jQuery / jQuery Mobile em uso, portanto achei sensato usar essas mesmas bibliotecas para a aplicao nova. Seria
interessante considerar o uso de UI5 aqui, porm eu achei que a curva de complexidade se tornaria muito ngreme para
implementar uma lgica de interface que, nas aplicaes que j existiam, era bem simples. E alm disso eu no estou
completamente vontade ainda para desenvolver em UI5, ento eu acabei pesando pro lado que eu conhecia melhor.
Resolvi, ento, usar esse projeto como base para essa srie de posts, onde eu pretendo explicar as tcnicas que eu usei
para desenvolver uma aplicao BSP com interface em jQuery Mobile. Observem bem que nessa ltima frase eu usei a
palavra tcnicas, porque eu no pretendo mostrar aqui a construo completa de uma aplicao se voc precisa de algo
assim, existem alguns posts no SCN como esse aqui e esse aqui tambm ou quem sabe esse no Sourceforge onde ao final
voc ter uma aplicao construda.
Enfim, com as ferramentas escolhidas, j possvel comear a desenvolver.

Preparando os recursos

Como estamos trabalhando com BSP, este o momento onde deve-se importar os recursos necessrios aplicao para o
repositrio MIME. A documentao diz que os objetos MIME disponveis para todas as aplicaes BSP ficam na pasta
/SAP/BC/BSP/[namespace]/PUBLIC (onde [namespace] pode ser tanto SAP como algum namespace do cliente), portanto
esse o local onde devemos importar as bibliotecas de jQuery. No caso do projeto, as bibliotecas de jQuery e de jQuery
Mobile j estavam presentes no repositrio, assim como o tema jQuery Mobile personalizado do cliente. Eu acabei
precisando importar apenas mais alguns plugins especficos para algumas tarefas, como o DateBox para criar campos de
seleo de data mais consistentes do que os do jQuery Mobile, e o Number para formatao de campos com dados
numricos (vou falar mais desses plugins nos prximos posts).

Customizando o login

At comear neste projeto, eu nunca havia desenvolvido muito em BSP fora de um ZHELLO_WORLD. Minha experincia com
desenvolvimento web dentro do SAP abrangia somente WebDynpro ABAP, e em todos os projetos onde eu trabalhei com
essa tecnologia at hoje o deploy das aplicaes sempre foi feito dentro de um Portal (EP). Esse tipo de implantao facilita
alguns aspectos do desenvolvimento. Um deles a autenticao de usurios: na maioria das vezes, uma aplicao WDA
implantada num EP no precisa se preocupar com login, logof ou sesses de usurios, porque esses elementos so tratados
pelo prprio portal.
Mesmo assim, em alguns momentos eu j precisei customizar o servio ICF de algumas aplicaes WDA. S que com esse
projeto eu acabei descobrindo que os servios tem muito mais opes do que apenas Ativar / Desativar.

Configurando pginas de erro na SICF


As telas acima mostram um exemplo de configurao de um servio do ICF mais especificamente da configurao de
pginas de erro do servio. Estas pginas se chamam assim porque so as respostas definidas no servio a erros especficos
que podem ocorrer durante o uso da aplicao: erros de login ( HTTP 401 ), erros em geral da aplicao ( HTTP 500 ), erros
ao no encontrar algum recurso no servidor ( HTTP 404 ) e pginas de resposta para logof.
Todas essas pginas podem ser customizadas para um servio de uma aplicao BSP, e interessante que se faa isso.
Porm, a tela de login talvez seja a mais importante de todas no caso de aplicaes mveis porque, a no ser que se trate de
algum caso mais raro onde dispositivos mveis fazem uso de Single Sign-On, a tela de login sempre ser a primeira a ser
exibida quando o usurio acessa o link da aplicao. Dessa maneira, importante que a pgina de login seja to responsiva
quanto as pginas da aplicao.
O que temos a fazer aqui criar uma classe filha da CL_ICF_SYSTEM_LOGIN e indicar essa classe dentro da configurao
System Logon do servio na SICF, atravs de Error Pages > Logon Errors > selecionar System Logon e clicar no
boto Configuration > na tela nova, selecionar Define Service-Specific Settings > no grupo Logon Layout and Procedure,
selecionar Custom Implementation e indicar em ABAP Class o nome da classe gerada.

A CL_ICF_SYSTEM_LOGIN tem alguns mtodos com o nome HTM_*, que so responsveis por criar o markup das pginas de
login os mtodos que merecem destaque entre esses so o HTM_LOGIN, que o responsvel propriamente por criar a
pgina de login, e o HTM_CHANGE_PASSWD, que constri a tela para mudana de senha. A lgica implementada nessas
pginas bem simples: o usurio deve preencher seu ID e senha e clicar em um boto que disparar um evento especfico
atravs de uma funo JavaScript pr-definida. Para isso, todos os mtodos HTM_* possuem um parmetro importing com o
nome IV_JAVASCRIPT, que contm as funes predefinidas para os botes, alm claro de um parmetro returning
chamado RV_HTML, que a string com o HTML gerado. No caso de uma tela construda com jQuery Mobile, podemos
concatenar o contedo do parmetro IV_JAVASCRIPT no markup logo aps importar as bibliotecas jQuery. Os mtodos
tambm possuem um outro parmetro importing chamado IV_HIDDEN_FIELDS, que traz um markup j
construdo, contendo os campos que NO esto selecionados no grupo Select Display na configurao (veja na imagem
acima), ou seja, campos que devem ficar escondidos. O valor desse parmetro pode ser inserido no incio do form que ser
montado pelo mtodo.
Alm dos mtodos, a classe tambm possui diversas constantes que definem os atributos id e name das tags de campos e
botes. Esta pgina do help da SAP fornece uma referncia para o uso dessas constantes. E podemos encontrar, ainda nessa
mesma classe, uma srie de outros atributos contendo textos que so construdos automaticamente para textos de labels e
botes, de modo a facilitar a construo de layout como, por exemplo, o atributo M_TXT_LABEL_USER, que serve de label
para o campo de ID do usurio, ou o atributo M_TXT_BUTTON_LOGIN, que contm texto para o boto que realiza o login.
Felizmente, existe uma referncia standard de como construir uma tela de login e tambm uma tela de mudana de senha.
Essa referncia a classe CL_ICF_EXAMPLE01_LOGIN, que constri as pginas em HTMLB. Partindo da implementao
dessa classe, basta ter em conta os pontos onde as funes JavaScript so chamadas e reconstruir o markup usando os
elementos do jQuery Mobile.

Enxugando a tela de logon com jQuery Mobile


Algumas dicas sobre a construo das telas de login:

Deixe a construo do HTML de retorno para um nico comando no final do mtodo. Os mtodos da
CL_ICF_EXAMPLE01_LOGIN misturam diversos CONCATENATEs ao longo do cdigo incluindo as tags HTML e construindo os
textos das variveis ao mesmo tempo, o que torna difcil de ver o resultado completo que ser retornado. Em vez disso,
melhor construir todas as variveis no comeo do mtodo e depois, como ltimo comando, construir todo o HTML no
parmetro de retorno. Isso facilita a visualizao do markup, de modo que voc no precise ter que executar o mtodo
apenas para poder ver o retorno. BONUS POINTS pra quem fizer isso usando string templates em vez de CONCATENATE (se
for possvel, claro).

No esquea das mensagens! O atributo M_LOGMESSAGES uma tabela que contm as mensagens relativas
ao login; se algum erro for encontrado, a tela de login ser chamada novamente e esse atributo voltar preenchido.
possvel identificar o tipo de cada mensagem (erro, aviso, informao) comparando o valor do campo M_LOGMESSAGESSEVERITY com as constantes definidas na classe CL_BSP_MESSAGES. A partir disso, cabe a voc definir como exibir cada
mensagem eu particularmente gostei da implementao simples usando um collapsible que foi feita nesse post.

Desligue o Ajax nos forms. O jQuery Mobile trata automaticamente os submits em forms usando Ajax, tentando
carregar o resultado de um POST dentro de um novo <div> na mesma pgina. No podemos deixar isso acontecer nas
pginas de login; para isso, basta um data-ajax="false" na declarao de cada form e est tudo resolvido.

Limite os mandantes e idiomas. Normalmente, voc no quer que o usurio faa login em alemo no mandante
000 para usar a sua aplicao portanto, limite os inputs de mandante (tabela T000) e de idioma (tabelas T002 e T002T)
usando drop-downs, dependendo do ambiente. Algumas funes relevantes para tratar os idiomas:
SYSTEM_INSTALLED_LANGUAGES, que retorna os idiomas que esto instalados no sistema, e
RSRA_GET_DEFAULT_LANGUAGE, que retorna o idioma padro de login do sistema.
Assim fecho o primeiro post dessa srie. No prximo, vou comear a falar da interface. Dvidas, indagaes ou sugestes?
Deixem nos comentrios a abaixo ou mandem um e-mail.

About the Author


Leo Schmidt ABAP profissional desde dez/2008. Meu negcio desenvolver ABAP, mas sem pensar s em ABAP: gosto de
fazer o SAP conversar com outras linguagens e sistemas, sempre de olho no Basis.

1.

Thiago says: March 31, 2015 at 1:26 pm


timo post. Recentemente ca no mesmo dilema de ter que desenvolver uma aplicao web e. responsiva. No manjava
nada de MVC, JavaScript, etc Acho que s assim para termos noo de que o mundo web no s restrito ao mundo
dotnet/java, e que ns de ABAP podemos sim fazer to bem feito quanto eles.

Reply

2.

Rodrigo F. Morais says: March 31, 2015 at 2:20 pm


Grande Lo, timo postestou navegando por esses mares de mobilecomo no h mais suporte ao SAPConsole a
mudana necessria, deixo a dica do SAP ITS Mobile, tem bastante material na SCN, normalmente usado para converso
das transaes de WM, porm j tive vrias experiencias com outras solues para aplicaes de browser ainda mais com
sua dica de jQuerysegue um documento interessante com alguns exemplos
ITS Asug
Abraos!

Reply

3.

Wagner Duarte says: May 25, 2015 at 6:29 pm


Leo timo Post! Como voc citou, eu tambm costumo desenvolver em Webdynpro aplicaes p/ web, e no conheo bem o
BSP, nessa sua nova aventura, voc deve ter aprendido bastante de BSP, tem alguns links interessantes sobre BSP ?
Tambm achei interessante a analise sobre UI5, essa dvida natural, pouca gente usa UI5 no Brasil para Web sem o
contexto do Hana.

Reply

Leo Schmidt says: May 26, 2015 at 11:22 am

o
Valeu Wagner!

Sinceramente, eu tenho pouca documentao sobre BSP, e eu espero explicar bem como eu fiz uso dele no terceiro post
dessa srie (alis o segundo sai hoje). Eu acho que a referncia do help da SAP, pra mim, foi suficiente, porque o uso do
framework de BSP que eu fiz foi mais trivial, j que no por via dele que eu resolvi coisas como navegao, renderizao,
atualizao de tela, etc., e sim diretamente pelo jQuery / jQuery Mobile.
Eu gosto bastante da ideia do UI5 e eu ainda vou fazer alguns posts sobre isso, mas como eu disse ali um framework que
eu no conheo muito bem ainda. Apesar disso eu sei que d pra fazer muita coisa com ele, e no necessariamente no
HANA como vc disse, afinal frontend.

Reply

Mauricio Cruz says: May 27, 2015 at 8:51 am

Acho bem legal usar o UI5 e etcs, mas a diverso toda dessa separao backend e frontend que voc pode usar o que voc
quiser. Naturalmente a SAP vai puxar o uso do UI5 por ser a biblioteca padro do Fiori, mas at a whatever, a gente usa o
que a gente quiser \o/

Reply

BSP + jQuery Mobile, ou a aventura de SAP-webdev Parte II: Frontend


E a seus consultor WD (Walking Dead), tudo bem? Aqui t tudo certo tambm.
Nessa segunda parte da srie eu vou falar de coisas que podem ser novidade pros desenvolvedores mais ABAPeiros:
tcnicas para desenvolver uma view com jQuery Mobile (que abreviarei como jQM neste post) para uma aplicao
com backend BSP. Se voc no est acostumado com desenvolvimento web, seria prudente checar os links que eu coloquei
na primeira parte dessa srie.

Ferramentas
Eu nunca subestimo o masoquismo das pessoas, mas eu acho que escrever e testar HTML, JavaScript e CSS na SE80 no
mnimo ruim. Felizmente, no necessrio fazer isso: voc pode escrever e testar a lgica e definio das suas views em
outros lugares / editores e depois importar para o SAP. Vou deixar aqui algumas dicas de ferramentas que eu uso:
Editor: uma indicao boa que peguei do prprio Maurcio aqui do ABAP Zombie o Sublime Text. um editor bacana que
tem vrias opes de plugins de automao, syntax highlighting para vrias linguagens, enfim, muito bom.
Desenho de telas: s vezes necessrio montar alguns mockups de telas para entender a lgica, ou mesmo para mostrar
como a aplicao vai se comportar. Eu gostei da verso gratuita do Moqups, porque os elementos j so bem parecidos com
os do jQM.
Testes: em certas situaes voc acaba tendo que bolar algo do capeta mirabolante com CSS pra alguma tela, ou voc
precisa mesmo entender como e quando aquele evento maldito incomum do jQM disparado, ou voc apenas quer ver se a
sua lgica no deu merda funciona. Existem vrios sites bacanas para esse tipo de teste, e o que eu uso o JSFiddle. Ele tem
um controle de verses bem simples, e voc pode compartilhar e criar forks de cdigos de outras pessoas com facilidade. Eu
tenho um dashboard com algumas coisinhas l, e voc pode criar a sua conta e criar um dashboard seu tambm.

Multi-HTML vs. multipage


Uma das primeiras decises a se tomar qual vai ser a arquitetura de pginas da aplicao. Seria melhor usar o
padro multi-HTML, onde cada pgina jQM fica num documento HTML separado, ou o padro multipage, onde as pginas
jQM esto todas no mesmo documento HTML? Existem argumentos a favor e contra o uso de cada um, como se v nesse
post aqui.

De maneira geral, se a sua aplicao tem uma pequena quantidade de telas, a escolha de arquitetura vai influir pouco na
performance. No caso do projeto que eu estou usando como exemplo nessa srie, porm, foram necessrias 10 telas com
lgica (pesada) de negcio e outras 4 s com links para navegao. No prudente que uma aplicao para dispositivos
mveis fique recarregando a cada mudana de pgina, dependendo assim bastante da rede, o que seria o caso se a
arquitetura multi-HTML fosse a escolhida. Portanto, eu escolhi o padro multipage, de modo que assim que o usurio
fizer login corretamente, todas as pginas jQM da aplicao sero carregadas no DOM, e somente a primeira pgina, a
pgina inicial, exibida (esse comportamento descrito na documentao do jQM). Assim, a navegao resolvida via Ajax
e fica quase independente do backend, e a view precisar ser carregada apenas uma vez para cada execuo da aplicao.
E por falar em Ajax

A importncia do Ajax
praticamente TODA ao que resulta em navegao, leitura ou alterao dos dados na view pode ser (ou ser) resolvida
com Ajax. Isso se torna uma parte essencial da aplicao quando se escolhe a arquitetura multipage, porque nesse caso no
temos roundtrips constantes ao servidor para esse fim. Como estamos usando jQuery, portanto imperativo que se entenda
e se utilize corretamente os mtodos que expem as funcionalidades Ajax, entre eles o mtodo $.ajax(), o mais low-level,
porm principalmente os mtodos simplificados $.get() e $.post().
Um detalhe importante sobre as chamadas Ajax que estas so assncronas, o que quer dizer que embora saibamos
exatamente o ponto de origem da chamada, no sabemos em que momento a resposta chegar do servidor. Os mtodos de
Ajax do jQuery possuem vrios parmetros onde podem ser indicadas funes de callback, que sero chamadas
dependendo do tipo da resposta e em pontos especficos antes ou depois do resultado.
Alm disso, os prprios mtodos Ajax retornam um objeto do tipo jqXHR, que basicamente um encapsulamento jQuery do
objeto XMLHttpRequest do browser, e de onde podem ser chamados outros mtodos para cada tipo de resposta do servidor,
em vez das ou adicionalmente s funes de callback. Ento uma chamada Ajax tpica ficaria, por exemplo, assim:
JavaScript
$.get('main.do?action=getServe
/* Aqui tratamos a resposta c
parmetro "data" o corpo d
$('#server_parameters').text(

$.get('main.do?action=getServerParameters', function(data, textStatus, jqXHR) {

/* Aqui tratamos a resposta caso a request tenha sido bem sucedida. O

parmetro "data" o corpo da resposta */

$('#server_parameters').text(data);

5
6

/* Se a chamada retornar um objeto JSON em vez de HTML ou texto puro,

possvel acess-lo j interpretado atravs do parmetro jqXHR */

dateFormat = jqXHR.responseJSON.dateFormat;

})

10

.fail(function(jqXHR, errorStatus, errorThrown) {

11

/* Este callback parte da interface Promise do objeto jqXHR, que

12

chamado caso a request falhe, e que est sendo chamado aqui de forma

13

encadeada a partir do retorno do $.get(). Se a resposta contiver dados,

14

como uma mensagem de erro ou mesmo um popup, podemos acess-los pelo

15

parmetro "jqXHR". Por exemplo: */

16

$('#message_area').html(jqXHR.responseText).show('fast');

17

});

Outro detalhe importante que os forms numa arquitetura multipage devem ser declarados sem o atributo action, porque
um submit em um form que contenha esse atributo resulta sempre em um POST no recurso indicado e num
subsequente refresh no documento, que como eu mostrei l no comeo um empecilho para uma arquitetura com apenas
um documento HTML. Isso muda um pouco a maneira de submeter os dados de um form; na maioria das vezes ser
necessrio passar diretamente os valores dos campos, ou usar algum mtodo de jQuery que retorne uma string de
parmetros, como o .serialize() ou o $.param(), para ento passar os valores como parmetros de URL em um GET ou
como corpo da request num POST. Um exemplo simples:

HTML
Default
<div data-role="page">
<div data-role="header">
<h1>Exemplo</h1>
</div>
<div role="main" class="ui-co

<div data-role="page">

<div data-role="header">

<h1>Exemplo</h1>

</div>

<div role="main" class="ui-content">

<form id="tela_selecao">

<input type="text" id="material" name="material" placeholder="Material" />

<div class="ui-field-contain">

<label style="margin-top:0">Unidade</label>

10

<b><span id="unidade">Nenhuma</span></b>

11

</div>

12

<input type="text" id="quantidade" name="quantidade" placeholder="Quantidade" />

13

</form>

14

<a href="#" id="buscar" class="ui-btn">Buscar unidade</a>

15

<a href="#" id="criar" class="ui-btn">Criar pedido</a>

16
17

</div>
</div>

Exemplo renderizado no JSFiddle

JavaScript
JavaScript
/* Ao clicar no boto "Buscar un
preenchido com a unidade do m
pretendemos alterar nenhuma in
mtodo GET). O backend possu
como essa busca ("buscarUnid

/* Ao clicar no boto "Buscar unidade", queremos que o span "unidade" seja

preenchido com a unidade do material que est no campo "material", e no

pretendemos alterar nenhuma informao no servidor (portanto, usaremos o

mtodo GET). O backend possui um mtodo que interpretar o parmetro "action"

como essa busca ("buscarUnidade"). Portanto: */

$('#buscar').on('click', function() {

var url = 'main.do?action=buscarUnidade&material=' + $('#material').val();

$.get(url, function(data) {

$('#unidade').text(data);

10

})

11

.fail(function(jqXHR) {

12

alert(jqXHR.responseText);

13
14
15

});
});

16

/* Alm da busca de unidades, temos outro boto que servir para criar um

17

pedido com base no material e na quantidade, ou seja, usando todos os campos

18

do form. Nesse caso, a request alterar os dados no servidor, por isso

19

usaremos o mtodo POST. O backend possui outro mtodo justamente para criar o

20

pedido, que responde ao valor "criarPedido". Logo: */

21

$('#criar').on('click', function() {

22

var url = 'main.do?action=criarPedido',

23

postData = $('#tela_selecao').serialize();

24

$.post(url, postData, function(data) {

25

alert(data);

26

})

27

.fail(function(jqXHR) {

28

alert(jqXHR.responseText);

29
30

});
});

Nos exemplos acima eu acabei j descrevendo outra caracterstica importante, embora j bem conhecida, para a definio
dos mtodos das requests de uma aplicao web: se a request vai apenas buscar dados do servidor, deve-se usar o mtodo
GET; se a request servir para alterar os dados no servidor, mesmo que apenas dentro da aplicao, deve-se usar o mtodo
POST. Aqui tem alguns argumentos sobre o porqu disso.
Mais um detalhe: um form mesmo sem action ainda pode sofrer um submit quando se pressiona ENTER. Esse
comportamento pode ser desabilitado com um pouco de JavaScript:
JavaScript
$(document).on('pagecontainer
// Fazendo o binding na criao
$(w indow ).on('keydow n', fun
if (event.keyCode === 13)
event.preventDefault();

$(document).on('pagecontainercreate', function() {

// Fazendo o binding na criao do pagecontainer

$(window).on('keydown', function(event) {

if (event.keyCode === 13) {

event.preventDefault();

return false;

7
8

}
});

});

interessante ter um elemento visual que indique quando a aplicao est parada esperando a resposta de uma request
Ajax. Para isso, podemos usar o loader do jQM. A maneira mais simples exibir o loader sempre que uma request for
disparada, e escond-lo quando a resposta chegar:
JavaScript
$(document).ajaxStart(function(
$.mobile.loading('show ');
});
$(document).ajaxStop(function(
$.mobile.loading('hide');

$(document).ajaxStart(function() {

$.mobile.loading('show');

});

$(document).ajaxStop(function() {

5
6

$.mobile.loading('hide');
});

Eventos
importante lembrar que ao usar jQM a view est sujeita aos eventos do jQM (obrigado, Capito bvio). Portanto, ao
fazer binding dos eventos da tela como cliques, abertura e fechamento de collapsibles, abertura e fechamento de popups,
dentre outros melhor faz-lo dentro dos callbacks de outros event bindings de eventos do jQM, como eu fiz no
exemplo acima onde eu desabilitei a funo do ENTER dentro do callback de criao do pagecontainer. O mesmo vale
para as chamadas Ajax.
Isso parece ser um detalhe de menor importncia, mas acredite quando eu digo que no . O jQM tem a tendncia de fazer
algumas coisas malucas quando se tenta mesclar os seus event bindings com os do jQuery. Eu quase fiquei doido tentando
descobrir porque os eventos dos botes que eu estava colocando na view estavam sendo disparados TRS VEZES para cada
clique, at eu mudar a declarao do binding para dentro de um evento pagecreate. Ento, em vez de fazer algo como
JavaScript
$(document).ready(function() {
$('#botao').click(function() {
// Cdigo do event handler
});
});

$(document).ready(function() {

$('#botao').click(function() {

// Cdigo do event handler

4
5

});
});

melhor fazer:
JavaScript

$(document).on('pagecreate', '#
$('#botao').click(function() {
// Cdigo do event handler
});
});

$(document).on('pagecreate', '#pagina1', function() {

$('#botao').click(function() {

// Cdigo do event handler

4
5

});
});

Adaptando paradigmas e elementos de telas


H certas coisas que o desenvolvedor ABAP est acostumado a fazer ao criar interfaces para SAP GUI que nem sempre so
fceis de se reproduzir fora desse meio. Em alguns casos, basta adaptar o elemento; em outros, preciso revisar a
funcionalidade da tela. Vejamos como fazer algumas adaptaes de elementos e paradigmas de interface para jQM:
Passagem de parmetros entre telas: isso bem comum em telas ABAP, e resolvemos em JavaScript do mesmo jeito que
em ABAP: usando variveis globais. Declare as variveis que serviro para passar parmetros entre pginas diretamente na
rea de scripts do <head>, tomando o cuidado de no declarar variveis com o mesmo nome dentro de funes. Se for
necessrio manipular as variveis no meio do caminho (limpar, validar, etc.), possvel faz-lo nos eventos do
pagecontainer, como o pagecontainerhide, que disparado aps a pgina origem da navegao ser totalmente
escondida, ou o pagecontainerbeforeshow, que disparado antes da animao de exibio da pgina destino ser
executada.
Matchcodes (ajudas de pesquisa, F4): um matchcode simples com valores fixos sempre pode ser reproduzido fielmente com
um <select>. J um matchcode mais complexo, com parmetros, abas ou ambos, vai exigir uma pgina ou um popup extra,
e isso significa construir uma lgica de passagem de parmetros entre telas e tambm pelo menos mais uma request Ajax
para fazer a busca; portanto, s construa se for realmente necessrio. Uma exceo neste caso o matchcode para seleo
de datas; ele pode ser perfeitamente refeito com <select>s para ano, ms e dia, mas neste caso eu prefiro usar um plugin
chamado DateBox, que possui um timo seletor de datas, mais flexvel do que o do SAP GUI inclusive.
Formatao de input:

Na maioria dos casos, os inputs podem ser feitos com type="text", e o atributo maxlength a melhor
maneira para limitar o comprimento do valor.

Para campos baseados em variveis ABAP do tipo c, possvel usar a propriedade CSS text-transform:
uppercase para deixar o texto em maisculas, porm isso s vai modificar o texto que est na tela portanto, necessrio
transformar o texto do campo em maisculas novamente quando os valores estiverem sendo tratados pelo backend.

Campos de data: uma boa maneira de format-los utilizando o j mencionado DateBox voc pode estilizar os
campos depois que a pgina foi criada, chamado o mtodo .datebox() e passando as propriedades conforme a
documentao do plugin. Uma boa prtica definir o formato da data a partir dos parmetros do usurio: para isso,

chame a BAPI_USER_GET_DETAIL e escolha o formato correspondente ao valor do campo DEFAULTSDATFM entre os formatos definidos no domnio desse campo;

traduza o formato SAP para o formato usado no DateBox: por exemplo, o tipo de formato de data mais
comum, que o 1 ( DD.MM.AAAA ), viraria %d.%m.%Y;

ao estilizar o campo, passe o formato definido para a opo overrideDateFormat.


Formatao de quantidades / valores em moeda outro problema para o qual precisamos de um plugin jQuery
nesse caso, eu uso o Number. A ideia parecida com a que eu expliquei para o DateBox: pegue a definio a partir do
campo DEFAULTS-DCPFM, compare com os valores fixos do domnio e passe os caracteres de separador de milhares e de
decimais para o mtodo que estiliza os campos, conforme a documentao do plugin.

Mensagens: essa uma rea mais aberta. possvel adotar uma linha de design um pouco mais moderna usando
elementos toast (que se chamam assim porque parecem com torradas pulando da torradeira) usando plugins como o
jquery.mobile.toast, mas eu considero que os popups do jQM j servem bem pra esse propsito. Eu fiz esse fiddle aqui bem
simples pra mostrar como exibir algumas mensagens em popups jQM.
Tabelas: no muito prtico ou funcional mostrar uma tabela com uma tonelada de informaes numa tela de dispositivo
mvel, como faramos normalmente num ALV. As tabelas de jQM so pensadas para terem poucas colunas (de 5 a 7, no
mximo, um intervalo razovel) e serem responsivas, mudando de formato em resolues menores veja os exemplos
de reflow nos demos de jQM. Uma soluo para exibir itens com muitos dados usar um collapsibleset, onde somente se
exibe uma lista de descries dos itens e os detalhes aparecem quando se clica em uma linha (escondendo detalhes de
outro item que porventura j estejam sendo exibidos). Outra soluo, sem usar elementos nativos de jQM, implementar
um carrossel, onde tambm se exibe um item por vez e a navegao entre itens feita horizontalmente. Essa tcnica
precisa de um pouco de CSS e jQuery pra funcionar, porm claro que j existem vrios plugins que fazem isso, como o OWL
Carousel ou o slick. Eu fiz, como exemplos, um fiddle com um carrossel bem rudimentar e um outro mais complexo, com
mais alguns controles, ambos sem usar plugins e sem muita estilizao, mas mostrando como o conceito funciona.
Tirando tudo isso, o uso de jQuery e jQM oferece possibilidades praticamente ilimitadas para desenvolver interfaces. Por
exemplo, o projeto que eu estou usando de exemplo nessa srie, que uma aplicao para coleta de materiais, se
beneficiaria muito com um leitor de cdigo de barras. Como integrar isso na aplicao? Com um plugin de jQuery, claro. O
WebCodeCam uma implementao simples que usa a API getUserMedia para capturar a imagem da cmera e identificar
cdigos de barra de vrios tipos. O nico problema que no funciona no Safari nem no IE.

Bom, isso por enquanto. Esse post tem mais links do que artigo da Wikipedia, mas a maioria aponta pras documentaes
de jQuery e jQM, ento basta ir l pra ter uma referncia mais completa e concisa. Espero que eu tenha conseguido
ajudar quem est desenvolvendo ou precisando desenvolver views BSP com jQM a no ficar completamente sem rumo.
At a prxima (e ltima) parte, onde eu vou falar do desenvolvimento de backend (e onde finalmente vai ter um pouco mais
de ABAP).

Referncias (tambm conhecido como TL;DR ou t de sacanagem que eu vou ter que ficar
caando link)

jQuery API / jQuery Mobile API e jQuery Mobile Demos

Sublime Text

Moqups

JSFiddle / Meu dashboard l

Multipage template vs Multi HTML template in jQuery Mobile

HTTP Methods: GET vs. POST

Carousel design pattern

Navigator.getUserMedia()

Plugins:

DateBox

jQuery Number

jquery.mobile.toast

OWL Carousel

slick

WebCodeCam

Edit
Eu imaginei que fossem faltar algumas vrias coisas mesmo nesse turbilho de informaes a. Vamos l:

No ficou claro no post, mas ao contrrio do que se faz normalmente com BSP puro, a ideia aqui construir
a view SEM NENHUM CDIGO ABAP. O markup praticamente s HTML5, totalmente independente do BSP, com exceo
de tags de OTR para os textos ( <%= otr(...) %> ) e da tag de pgina (normalmente eu uso <%@page language="abap"
otrTrim="true" %> ). A ideia aqui escrever a view com HTML, JavaScript e CSS de maneira que se ela fosse removida
totalmente do BSP e implementada junto com outro backend, mantendo somente a estrutura dos recursos e substituindo as
tags de BSP, a lgica da view funcionaria exatamente da mesma maneira.

De maneira nenhuma, absolutamente, NUNCA, eu repito, NUNCA, coloque lgica de negcio no JavaScript.
JavaScript cdigo que 1) roda no browser, 2) pode ser depurado e analisado em tempo de execuo, e 3) fica em cache,
portanto isso um problema de segurana. O JavaScript da view deve somente fazer coisas muito triviais com relao aos
dados, que tambm no tenham relao alguma com dados de negcio, como por exemplo montar um seletor de ano:

JavaScript
$('#tela_de_selecao').find('selec
var year = new Date().getFul
for(var i = year - 10; i < year
$(this).append('<option val
$(this).selectmenu('refresh',

$('#tela_de_selecao').find('select.ano').each(function() {

var year = new Date().getFullYear();

for(var i = year - 10; i < year + 11; i++)

$(this).append('<option value="' + i + (i === year ? '" selected="selected">' : '">') + i + '</option>');

5
6

$(this).selectmenu('refresh', true);
});

Lgica de negcio fica no cdigo ABAP, e isso fica no BSP. Falarei disso no prximo post.

About the Author

Leo Schmidt ABAP profissional desde dez/2008. Meu negcio desenvolver ABAP, mas sem pensar s em ABAP: gosto de
fazer o SAP conversar com outras linguagens e sistemas, sempre de olho no Basis.

1.

Mauricio Cruz says: May 27, 2015 at 8:58 am


Muito legal, principalmente os links.
JSFiddle uma das melhores coisas que inventaram. Usei muito para conseguir compartilhar um erro em fruns como o
Stackoverflow e deixar que outras pessoas avaliem e possam me ajudar com um erro. Exemplo: eu perguntando sobre JQM.
Valeu, abs!

Reply

2.

Mauro Laranjeira says: May 27, 2015 at 9:07 am


Grande post Leo parabns..
Cara, estou com 1 milho de duvidas, haha Mas acredito que seja porque nunca trabalhei diretamente com o BSP puro,
trabalhei bastante com o BSP do CRM, que bem diferente.
Voc usa um editor externo e depois importa para o MINE do SAP? Como ficam as regras do negocio, tudo misturado no JS
com ABAP? E a consulta no banco, ficam na pagina do BSP ou como montaria um MVC loko?
Fiquei doido com esse post ae rs
Cara, curti muito esse post, mais uma vez parabns nois

Reply

Leo Schmidt says: May 27, 2015 at 9:39 am

o
Valeu Mauro!

Eu infelizmente tive que deixar pra falar de BSP depois de falar de frontend, porque tem certas coisas que no d pra
explicar como fazer no BSP sem apresentar antes o que eu fiz com JS, como por exemplo as chamadas em Ajax. Mas, com o
risco de adiantar aqui algumas coisas do prximo post, vamos l:
Sim, como eu disse ali eu escrevo tudo de HTML, JS e CSS no Sublime e depois eu importo pro BSP. Vou falar melhor sobre
isso e sobre como isso organizado na aplicao BSP no prximo post.
No, no tem e no deve ter nenhuma lgica de negcio dentro de JS. Cdigo da view s pode servir pra manipular a
view. Em alguns raros momentos voc pode MONTAR JavaScript dentro do ABAP (que o que o standard faz no caso da tela
de login, como eu falei no outro post, por exemplo), e em vrios casos eu monto HTML dentro do ABAP, mas lgica de
negcio NUNCA (srio, NUNCA). O HTML que eu construo no tem NADA de ABAP. Nada mesmo.
Eu pretendo explicar o MVC que eu estou usando aqui no prximo post tambm, mas sim, coisas que envolvam o banco de
dados (portanto, lgica de negcio) acontecem no cdigo do BSP e NUNCA (srio, NUNCA) aqui no JS.
Vou dar um edit aqui no post pra compartilhar essas coisas com a galera
nis!

Reply

Mauro Laranjeira says: June 8, 2015 at 9:27 pm

Leo,

Muito show.. estou com bilhes de perguntas, mas vou esperar os prximos posts, tomar vergonha na cara e tentar fazer
alguma coisa usando o Ajax.
vlw mesmo

BSP + jQuery Mobile, ou a aventura de SAP-webdev Parte III: Backend


Acho que no demorou tanto quanto a saga do Freeza, mas sim caros zumbis, chegamos ao final desse guia! Vou falar
agora da parte principal do desenvolvimento: a aplicao BSP. Aqui vou mostrar como estruturar os recursos no backend e
tambm como ele vai responder a tudo o que acontece no frontend.

mas antes, um pouco mais de frontend


Lembra, l primeira parte, quando eu disse que necessrio subir as bibliotecas de jQuery e jQuery Mobile e os plugins no
repositrio MIME do SAP? Ento, se voc fez o frontend fora da SE80, bem provvel que o cdigo que voc fez ainda no
esteja referenciando as bibliotecas que esto no repositrio. Os seus headers podem estar mais ou menos assim:
Default
<!doctype html>
<html>
<head>
<meta name="view port" co
<link rel="stylesheet" href=

<!doctype html>

<html>

<head>

<meta name="viewport" content="width=device-width, initial-scale=1">

<link rel="stylesheet" href="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.css" />

<script src="http://code.jquery.com/jquery-1.11.3.min.js"></script>

<script src="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.js"></script>

<!-- outros scripts, plugins e stylesheets vo aqui -->

</head>

10

<body>

11
12
13

<!-- resto da pgina aqui -->


</body>
</html>

O endereo da aplicao BSP, na maioria das vezes, vai ser algo como http://[servidor]:[porta]/sap/bc/bsp/
[namespace]/[aplicao]. Aproveitando essa estrutura, podemos referenciar de maneira indireta as bibliotecas que
esto disponveis globalmente. Por exemplo, se voc tiver organizado as bibliotecas no repositrio MIME mais ou menos
com a mesma estrutura do CDN do jQuery, desse jeito:

Voc consegue mudar as declaraes acima por algo assim (os endereos sempre so case insensitive):
Default
<!doctype html>
<html>
<head>
<meta name="view port" co
<link rel="stylesheet" href=

<!doctype html>

<html>

<head>

<meta name="viewport" content="width=device-width, initial-scale=1">

<link rel="stylesheet" href="../public/jquery/mobile/1.4.5/jquery.mobile-1.4.5.min.css" />

<script src="../public/jquery/jquery-1.11.3.min.js"></script>

<script src="../public/jquery/mobile/1.4.5/jquery.mobile-1.4.5.min.js"></script>

<!-- outros scripts, plugins e stylesheets vo aqui -->

</head>

10

<body>

11
12
13

<!-- resto da pgina aqui -->


</body>
</html>

E agora eu posso finalmente explicar o porqu de usar o repositrio MIME e fazer essas mudanas no header: pra atender
a poltica de segurana dos navegadores que se chama same-origin policy (poltica de mesma origem). Isso serve tanto
para views que voc vai usar no BSP como para as que voc definiu nos mtodos da classe de login.
Outro detalhe que d pra perceber pela imagem e pelo cdigo: uma prtica comum em desenvolvimento web fazer
verses minified (minimizadas ou comprimidas) de todos os arquivos que compem as pginas, com o mesmo nome mais a
extenso .min.[extenso original], de modo que a aplicao trafegue uma quantidade menor de dados entre servidor
e navegador. Em tempo de desenvolvimento ou de debug, referencia-se o arquivo original, e depois que tudo estiver pronto,
comprimimos e mudamos as referncias para apontar para os arquivos comprimidos. O Sublime Text, que eu indiquei
no post anterior, tem alguns packages que fazem isso, como por exemplo o Minify (para a glria da obviedade!), que
comprime JavaScript e CSS. Eu no achei ainda nenhum package bacana pra minimizar HTML no Sublime, ento eu uso
ferramentas on-line mesmo como o HTML Minifier.

Estruturando a aplicao
Eu pensei em colar aqui uma imagem com o famoso diagrama do MVC, mas eu no sabia qual escolher:

Tem at um com o Homer ali


Vamos tentar o segundo ali mesmo:

O fluxo representado por esse diagrama basicamente o que a aplicao BSP deve fazer:

1.

Usurio envia uma request HTTP ao controller;

2.

Controller requisita dados do model;

3.

A resposta depende do contedo: se a request foi comum, pedindo por uma view, a aplicao a
instancia e esta exibida ao usurio; se a request foi feita via Ajax, os dados interpretados
so devolvidos diretamente do controller para a view pela response, que ento os interpreta e exibe o
resultado ao usurio.
Dessa maneira, uma aplicao BSP mais bsica que use jQuery / jQuery Mobile ser composta de uma classe para
o controller e uma classe para o model. A view no precisa necessariamente de uma classe prpria, porque a ideia que a
manipulao da view seja feita atravs dos scripts inseridos na pgina, sem interveno ABAP mas se voc tiver que montar
HTML muito complexo ou de maneira muito frequente dentro dos mtodos do controller (vou falar sobre isso mais pra
baixo), talvez seja melhor ter uma classe que faa somente isso. Essa estrutura pode ser repetida quantas vezes forem
necessrias; se a lgica de tratamento das requests/responses ou da seleo dos dados suficientemente complicada para
que haja separao em mais controllers ou models, esse o caminho.
Mas Leo, eu posso escrever tudo direto num controller s! Pra qu eu vou criar trocentas classes s pra UMA aplicao?
Porque eu espero que voc vai ser uma pessoa boa e seguir a arquitetura MVC. Afinal, voc no quer deixar um ninho de
rato em forma de classe pra quem for dar manuteno na aplicao depois, certo? CERTO? Bom ento.
A estrutura do BSP, usando a arquitetura multipage no frontend, ficaria mais ou menos assim:

Por partes, vamos.

Caractersticas da aplicao

Nada muito complexo por aqui:

Em Initial BSP (BSP pgina inicial) se indica o nome do controller principal da aplicao;

Normalmente no necessrio indicar uma Application Class (Classe de aplicao), mas se for necessrio
segregar a lgica da aplicao da aplicao em si, podemos indicar uma classe aqui, que pode ser acessada atravs do
atributo APPLICATION do controller;

No necessrio indicar nada em Theme (Tema), porque carrega-se os temas diretamente pelo markup com
as tags <link>;

A questo do estado da aplicao aberta. possvel desenhar a aplicao de maneira que no se dependa de
dados guardados no model, caso onde a opo Stateful (Com status) pode ficar desmarcada. Porm, se a aplicao
trata uma quantidade muito grande de dados ou tem um fluxo lgico muito complexo, melhor manter estados e essa
opo precisaria ficar marcada;

Supports Portal Integration (Suporta integrao Portal) depende da sua aplicao. A integrao com o Portal
geralmente tem a ver com navegao e gerenciamento de sesses, parecido com o que acontece com aplicaes Webdynpro
ABAP. Ative conforme necessrio;

XSRF Protection (Proteo XSRF) a proteo do framework BSP para prevenir cross-site request forgery. Esta
SAP note explica o que e como usar essa opo.

Objetos MIME
Aqui onde se deve importar o cdigo especfico da sua view: o HTML descomprimido, os scripts comprimidos e
descomprimidos, os stylesheets comprimidos e descomprimidos, e quaisquer outros objetos estticos especficos para a sua
aplicao: logotipos, vdeos, udios, PDFs, etc. No HTML possvel referenciar diretamente os objetos que voc importar
usando somente o nome dos mesmos. O exemplo do cabealho que eu usei acima, ento, ficaria:
Default

<!doctype html>
<html>
<head>
<meta name="view port" co
<link rel="stylesheet" href=

<!doctype html>

<html>

<head>

<meta name="viewport" content="width=device-width, initial-scale=1">

<link rel="stylesheet" href="../public/jquery/mobile/1.4.5/jquery.mobile-1.4.5.min.css" />

<script src="../public/jquery/jquery-1.11.3.min.js"></script>

<script src="../public/jquery/mobile/1.4.5/jquery.mobile-1.4.5.min.js"></script>

<!-- outros scripts, plugins e stylesheets vo aqui -->

<link rel="stylesheet" href="style.min.css" />

10

<script src="script.min.js"></script>

11

</head>

12

<body>

13

<!-- resto da pgina aqui -->

14
15

</body>
</html>

View

Aqui, tambm, nada extraordinrio:

Observe, em primeiro lugar, que a view contm o cdigo HTML comprimido, que ficar na aba Layout portanto o
nome index.min.htm. A pgina com o cdigo original descomprimido fica como objeto MIME do BSP, para futura
referncia/manuteno;

importante deixar o atributo Compression (Comp.pginas) em branco (com o valor None ou nenhuma),
porque os outros tipos de compresso podem afetar a sintaxe do HTML que j esteja minimizado;

O atributo W/O Script Code (sem cd.script) deve ficar desmarcado, pois a pgina contm scripts;

O Page Type (Tipo de pgina) View (Viso), e voc pode indicar qualquer controller ali (contanto que a classe seja
descendente da CL_BSP_CONTROLLER voc pode inclusive indicar ela prpria);

Esta pgina no ser uma pgina de erro (falei sobre elas na primeira parte da srie), portanto o atributo Is Error
Page fica desmarcado. Normalmente no se atribui aqui uma pgina de erro especfica, pois as mensagens podem ser
exibidas com outras tcnicas (que eu expliquei na segunda parte da srie), porm em Assigned Error Page (Pg.erro
atribuda) voc pode indicar uma outra pgina dentro da aplicao que servir como pgina de erro;

Por fim, mantm-se desmarcado o atributo Delta Handling (Tratmto.delta), porque no queremos que o
framework do BSP se intrometa na maneira como carregamos as pginas da aplicao.

Controller

Assim como nas outras pginas de configurao, nada muito estranho:

O nome do controller pode ser como voc quiser, e no precisa necessariamente terminar com .do. Para
o controller principal comum usar main;

Em Controller Class (Classe controlador) indica-se a classe criada para servir de controller da aplicao. Esta classe
deve ser descendente da CL_BSP_CONTROLLER;

A opo Start BSP (BSP incio) funciona em conjunto com a opo XSRF Protection da aplicao, portanto veja a
nota que eu mencionei mais acima para entender como us-la;

As opes de pgina de erro funcionam aqui da mesma maneira que funcionam na view;

Com relao ao estado, a escolha aqui a mesma que foi feita para a caracterstica da aplicao em si, com a
diferena que o estado do controller pode ser mantido (stateful) independentemente do estado da aplicao;

O armazenamento em cache pode ter um tempo maior do que zero, mas isso funciona melhor em
aplicaes stateless. Em aplicaes stateful as opes de Caching podem ficar em zero mesmo;

Compression (Compresso) e HTTPS so opcionais. A primeira comprime a pgina antes de envi-la ao navegador,
e a segunda trafega-a usando SSL;

Assim como na view, deixe desmarcada a opo Delta Handling (Tratmto.delta).

Classe do controller
Essa classe responsvel por receber, tratar e responder as requests. Como j falei algumas vezes aqui, essa classe precisa
ser descendente da CL_BSP_CONTROLLER.

A ideia aproveitar o mnimo dessa herana apenas para fazer com que o controller responda as requests, tanto as geradas
pelo usurio quanto as feitas via Ajax. Para isso, necessrio:

1.

Redefinir e implementar o mtodo DO_INIT. A implementao desse mtodo tem uma


funo muito simples, que inicializar o(s) model(s) e guardar a referncia da instncia. Para isso,
basta chamar o mtodo CREATE_MODEL:
ABAP
METHOD do_init.
me->model ?= me->create_mo
class_name = 'Z_MINHA_CL
model_id = 'MINHA_CLASS
).

METHOD do_init.

me->model ?= me->create_model(

class_name = 'Z_MINHA_CLASSE_DO_MODEL'

model_id = 'MINHA_CLASSE_DO_MODEL'

).

ENDMETHOD.

(FINALMENTE chegamos no ABAP, hein?) O parmetro model_id serve para encontrar a instncia
de model correta no atributo M_MODELS atravs do mtodo GET_MODELS. Se voc vai trabalhar com
apenas um model (como o caso desse exemplo), mais prtico guardar a instncia do
model diretamente num atributo novo da classe, como esse me->model que eu usei no exemplo
acima, que no caso referencia a classe Z_MINHA_CLASSE_DO_MODEL.
2.

Redefinir e implementar o mtodo DO_REQUEST. Essa a implementao principal. O fluxo


basicamente como nesse exemplo aqui:
ABAP
METHOD do_request.
DATA: cdata
TYPE string,
code
TYPE i,
content_type TYPE string,

METHOD do_request.

2
3

DATA: cdata

TYPE string,

code

TYPE i,

content_type TYPE string,

form_fields TYPE tihttpnvp,

message_type TYPE sy-msgty,

reason

TYPE string.

9
10

* Assim como para o model, temos um atributo separado na classe para

11

* guardar a instncia da view. Usamos aqui esse atributo para saber se a

12

* view j foi chamada:

13
14

IF me->view IS INITIAL.

15
16

* A instncia da view ainda est vazia, portanto faremos s a

17

* inicializao e chamada da view:

18
19

me->view = me->create_view( view_name = 'index.min.htm' ).

20

me->call_view( me->view ).

21
22

ELSE.

23
24

* A instncia da view, aqui, j existe, portanto sabemos que a request

25

* s pode ter sido feita via Ajax. Lembram dos exemplos de request

26

* Ajax do post sobre frontend? Eles tinham endereos mais ou menos

27

* assim:

28
29

* main?action=algumaCoisa&...

30
31

* Pois bem, esse atributo de URL chamado ACTION a chave para

32

* entender a request. Ento vamos busc-lo:

33
34
35

CASE me->request->get_form_field_cs( 'action' ).

36

Uma request GET espera uma resposta com dados em algum formato

37

(HTML, JSON, XML, etc.) a partir de algum parmetro. Ento podemos

38

ter um mtodo que retorne somente os dados, como por exemplo:

39
40

WHEN 'getMaterialDescription'. "GET

41
42

cdata = me->get_material_description( me->request->get_form_field_cs( 'material_number' ) ).

43
44

WHEN 'getUnitDescription'. "GET

45
46

cdata = me->get_unit_description( me->request->get_form_field_cs( 'material_unit' ) ).

47
48

Se tivermos vrios parmetros, a interface do mtodo muda um pouco:

49
50

WHEN 'getMaterials'. "GET

51
52

me->request->get_form_fields_cs(

53

CHANGING

54

fields = form_fields

55

).

56
57

me->get_materials(

58

EXPORTING

59

im_form_fields = form_fields

60

IMPORTING

61

ex_cdata

62

ex_content_type = content_type

63

ex_message_type = message_type

64

= cdata

).

65
66
67

WHEN 'get...'. "GET

68

cdata = me->get_...

69
70

J uma request POST pretende alterar dados a partir de parmetros

71

informados pelo usurio. Os parmetros de uma request POST

72

normalmente so enviados no corpo da request, codificados em

73

string da mesma maneira que seriam numa request GET - portanto

74

para l-los precisamos da ajuda da classe CL_HTTP_UTILITY. Como

75

retorno, normalmente temos uma mensagem.

76
77

WHEN 'createGoodsMovement'. "POST

78
79

me->create_goods_movement(

80

EXPORTING

81

im_form_fields = cl_http_utility=>string_to_fields( me->request->get_cdata( ) )

82

IMPORTING

83

ex_cdata

84

ex_content_type = content_type

85

ex_message_type = message_type

86

= cdata

).

87
88

WHEN 'saveInventoryCount'. "POST

89
90

me->save_inventory_count(

91

EXPORTING

92

im_form_fields = cl_http_utility=>string_to_fields( me->request->get_cdata( ) )

93

IMPORTING

94

ex_cdata

95

ex_content_type = content_type

96

ex_message_type = message_type

97

= cdata

).

98
99

WHEN 'set...'. "POST

100
101

me->set_...(

102
103

WHEN OTHERS.

104
105

Neste caso temos uma request Ajax sem o atributo action, ou seja,

106

no uma request Ajax legtima para a aplicao. Isso pode

107

acontecer, por exemplo, quando o usurio executa um refresh (F5)

108

na pgina. Portanto, sabemos que a view j est criada, e basta

109

cham-la novamente:

110
111

me->call_view( me->view ).

112

RETURN.

113
114

ENDCASE.

115
116

* Se o processamento da request Ajax resultou em erro, precisamos

117

* informar um cdigo de erro na resposta para que o frontend a

118

* interprete corretamente:

119
120

IF message_type = 'E'.

121

code = 422. "Unprocessable Entity - RFC 4918

122

reason = 'Erro ao processar a request'(e01).

123

ELSE.

124

code = 200. "OK

125

reason = 'OK'.

126

ENDIF.

127
128

me->response->set_status(

129

code = code

130

reason = reason

131

).

132
133

* Os mtodos de Ajax do jQuery so capazes de reconhecer

134

* automaticamente o tipo do contedo da resposta, mas podemos tornar

135

* as coisas mais claras indicando explicitamente valores como

136

* 'application/json' ou 'application/xml', conforme o retorno do

137

* handler:

138
139
140
141

IF NOT content_type IS INITIAL.


me->response->set_content_type( content_type ).
ENDIF.

142
143

* Por fim, anexamos o contedo da resposta:

144
145
146
147

IF NOT cdata IS INITIAL.


me->response->set_cdata( cdata ).
ENDIF.

148
149

ENDIF.

150
151

ENDMETHOD.

U Leo, mas de onde veio esse cdigo 422 pra erro? No pra usar o 500? No, porque 500 um
cdigo genrico pra dizer que aconteceu algum erro no servidor, e o framework do BSP j usa esse
cdigo pra informar dumps, o que adequado. Os erros que acontecem j dentro dos event
handlers na maioria das vezes so provocados por entradas mal-formadas, por culpa do usurio ou
do processamento ABAP, e no necessariamente por causa do servidor. Por isso o erro devolvido aqui
fica melhor na categoria 4xx (client error).
Ah mas ento porque no usar logo o 400 Bad request mesmo? Porque o problema no com
a request em si, mas sim com os dados contidos (pra falar mais empolado, no sinttico,
semntico). Por exemplo: se o cdigo do material no existe, isso no necessariamente um
problema com a request, mas sim com o prprio cdigo que pode estar errado. Eis um post explicando
um pouco sobre isso.
3.

Criar event handlers especficos para cada action Ajax. No precisam ser event handlers reais
no contexto de ABAP Objects, mas sim apenas mtodos que respondem a cada action Ajax definida
no frontend, como eu mostrei nesse ltimo exemplo. O fluxo de cada mtodo vai ser simples:
interpreta-se os parmetros da request, transformando os dados conforme necessrio, chama-se o

mtodo do model que tratar os dados e formata-se a resposta a ser devolvida ao DO_REQUEST. No
exemplo abaixo, temos um event handler que vai ao model buscar uma lista de materiais a partir do
centro e do depsito:
ABAP
METHOD get_materials.
DATA: material
TYPE s
material_descriptions TYPE
message_text
TYPE

METHOD get_materials.

2
3

DATA: material

TYPE string,

material_descriptions TYPE makt_tab,

message_text

number

plant

storage_location

TYPE string,
TYPE string,
TYPE werks_d,
TYPE lgort_d.

9
10
11

FIELD-SYMBOLS: <field>

TYPE ihttpnvp,

<material_description> TYPE makt.

12
13

* Antes de mais nada preciso traduzir a string de parmetros que vem

14

* da request para variveis que podemos usar em ABAP. O material

15

* continua em string aqui porque a ideia que seja possvel buscar

16

* tanto pelo MATNR como pelo MAKTX

17
18

LOOP AT im_form_fields ASSIGNING <field>.

19

CASE <field>-name.

20

WHEN 'number'.

21
22
23
24

material = <field>-value.
WHEN 'plant'.
plant = to_upper( val = <field>-value ).
WHEN 'storageLocation'.

25

storage_location = to_upper( val = <field>-value ).

26

WHEN OTHERS.

27

ENDCASE.

28

ENDLOOP.

29
30

* Chamamos o model:

31
32
33

me->model->get_materials(
EXPORTING

34

im_material

35

im_plant

36

im_storage_location

37

= material
= plant
= storage_location

IMPORTING

38

ex_material_descriptions = material_descriptions

39

ex_message_text

= message_text

40

ex_message_type

= ex_message_type

41

).

42
43

IF ex_message_type IS INITIAL.

44
45

* Se o model no devolver nenhuma mensagem, montamos um JSON com os

46

* dados:

47
48

ex_cdata = |\{"materials":[|.

49
50

LOOP AT material_descriptions ASSIGNING <material_description>.

51
52
53
54
55
56

CALL FUNCTION 'CONVERSION_EXIT_MATN1_OUTPUT'


EXPORTING
input = <material_description>-matnr
IMPORTING
output = number.

57
58

ex_cdata = |{ ex_cdata }\{| &

59

|"number":"{ number }",| &

60

|"description":"{ <material_description>-maktx }"|.

61
62

IF sy-tabix < lines( material_descriptions ).

63
64

ex_cdata = |{ ex_cdata }\},|.


ELSE.

65
66

ex_cdata = |{ ex_cdata }\}|.


ENDIF.

67
68

ENDLOOP.

69
70

ex_cdata = |{ ex_cdata }]\}|.

71
72

ex_content_type = 'application/json'.

73
74

ELSE.

75
76

* Caso contrrio, chamamos outro mtodo para construir um HTML com um

77

* popup para a mensagem:

78
79
80

me->build_message_data(
EXPORTING

81

im_type

= ex_message_type

82

im_text

= message_text

83

importing

84

ex_cdata

85

ex_content_type = ex_content_type

86

).

87
88

ENDIF.

= ex_cdata

89
90

ENDMETHOD.

O resultado desse mtodo um objeto JSON contendo um array de objetos representando os


registros da MAKT que correspondem busca feita pelo usurio, ou um outro objeto JSON com o tipo
e texto da mensagem que ser exibida em popup.
Existe um certo dilema sobre o tipo de contedo que deve ser usado na resposta de uma request Ajax.
melhor retornar JSON e montar a exibio pelo script, ou devolver HTML montado e somente
integr-lo na pgina, tambm pelo script? Essa deciso cabe ao desenvolvedor, e pode sem
problemas resultar em implementaes diferentes para cada mtodo. No projeto que eu estou
usando de exemplo, h um pouco de ambas as tcnicas: alguns mtodos devolvem HTML montado,
outros devolvem JSON. A regra que eu uso a seguinte: se for simples montar o HTML pelo script, o
mtodo retorna JSON; caso contrrio, o mtodo retorna o HTML j montado.

Classe do model
Aqui onde acontece a mgica, se por mgica entendermos o ncleo do trabalho ABAP validao complexa das entradas,
operaes com o banco de dados, chamadas de funes, etc. Esta classe precisa ser descendente da CL_BSP_MODEL, porm,
para este tipo de uso, no necessita da redefinio de nenhum dos mtodos herdados.
Se estivermos trabalhando com uma aplicao stateful, os resultados das operaes da aplicao ficaro armazenados em
atributos dessa classe, e ser necessrio controlar em alguns pontos especficos os valores desses atributos. Por exemplo,
uma tabela que represente o resultado da busca de um relatrio pode precisar ser limpa toda vez que se chama a pgina do
relatrio, da mesma maneira que se faz com variveis globais em um grupo de funes. Para isso necessrio criar uma
chamada Ajax na entrada de cada pgina, e tambm mtodos correspondentes no controller e no model para fazer a limpeza
dos atributos.
bom lembrar tambm que, numa aplicao stateful, as requests Ajax que resultam em um estado intermedirio (ou seja,
actions do tipo set*que apenas gravam dados nos atributos do model) tambm esto alterando dados no servidor e
portanto devem ser iniciadas com o mtodo POST.
Esta classe deve esperar parmetros de entrada em seus mtodos com dados j convertidos para os tipos ABAP, o que deve
ser feito anteriormente pelo controller. Da mesma forma, os dados gerados pelo processamento do model so apenas
retornados para o controller, que ser responsvel por format-los adequadamente e inclu-los na resposta, conforme o
exemplo de event handler que est acima portanto essa classe no deve ser responsvel por montar HTML ou JSON. As
mensagens, por exemplo, podem ser chamadas com o uso de MESSAGE ... INTOe retornadas em uma string, retornando
tambm o valor de SY-MSGTY.

Assim chegamos ao fim desse guia maluco. Espero ter ajudado vocs a terem uma ideia de como usar tecnologias
de frontend, e de como integrar isso com o BSP, e qual o papel de cada um numa aplicao. No a coisa mais nova em
folha em termos de desenvolvimento web pra SAP, mas pra quem gosta de interface isso d um sabor diferente de
WebDynpro ABAP e de SAP GUI. Espero que eu consiga mais pra frente fazer um guia espelho desse, usando Gateway e UI5,
mas por enquanto isso.
Dvidas, reclamaes ou sugestes, favor entrar em contato com o departamento de comentrios abaixo ou via e-mail. At
mais!

About the Author


Leo Schmidt ABAP profissional desde dez/2008. Meu negcio desenvolver ABAP, mas sem pensar s em ABAP: gosto de
fazer o SAP conversar com outras linguagens e sistemas, sempre de olho no Basis.

2 Responses to BSP + jQuery Mobile, ou a aventura de SAP-webdev Parte III: Backend

1.

Flavio Furlan says: June 25, 2015 at 5:29 pm


Muito interessante! Quando voc fizer esse guia na SAPUI5 + Gateway estarei na primeira fila para pegar meu exemplar
Confesso que meu critrio para escolha de qual diagrama MVC escolher foi o mesmo que o seu:
http://abap101.com/2012/04/01/falsa-programacao-orientada-objetos/
Abraos!

Reply

2.

Mauricio Cruz says: July 6, 2015 at 9:39 am


Ficou animal! (s acabei de ler hoje haha).
Tendo trabalho com voc com bsps tempos atrs, muito legal ver quantas melhorias voc fez da nossa singela arquitetura
de primeira viagem, principalmente de performance (com a minificazizacao) e uso de JSONs
Parabns e abs mano!

Reply

Mstico mundo de BSP (Business Server


Pages)
J ouvi dizer que as Tags do BSP so inventadas na hora, assim como estatsticas em conversas informais
Bem semelhante ao F1, existe na SE80 explicaes e utilizaes das Tags BSP e Tags HTML.
Acesse SE80 -> Tag Browser

Tag Browser

Voc pode navegar nas categorias das Tags, tanto para BSP (Extenses BSP) como para HTML.
Outra forma de abrir o menu do Tag Browser seria na SE38, clique no menu Ambientes -> Ferramentas Web -> Tag Browser.

A SAP foi to boazinha


exemplos o/

que detalhou a explicao dos parmetros das Tags e colocou ate programas de

Exemplo:

Como criar um boto com uma Tag BSP?


Acesse SE80 -> Tag Browser -> Extenses BSP -> Transportveis -> htmlb -> <htmlb:button>
Sero exibidos todos os parmetros possveis para esta tag.

Tag para boto em BSP


Mas como usar esse treco comando?
Para visualizar a explicao da Tag, de um duplo clique sobre a mesma 8)
Aparece um popup com a explicao da Tag, explicao dos parmetros e at um programa de exemplo.

Ajuda Tag <htmlb:button>

Para executar o programa de teste, acesse SE80 -> Repository Browser -> Aplicaes BSP -> <nome do programa de
exemplo>, aperte enter, d um clique com o boto direito do mouse no nome do programa -> testar.

Vai abrir o navegar pedindo o usurio e senha do SAP. Logo aps abre a pgina do programa de exemplo.

Programa de exemplo SBSPEXT_HTMLB


Certo Zombizada eu sei que este exemplo no resolve todos os problemas de BSP, mas ajuda na procurar das tags e suas
utilizaes.
Abraos a todo aquele que inventam estatsticas para explicar algo.

About the Author


Mauro Laranjeira Motoqueiro fantasma... curandeiro do SAP desde 2006... trago o go-live perdido em um fim de semana...
junto 9 mulheres para fazer um filho em um ms... acreditador em histrias de Basis... garimpeiro de dados de teste...