Académique Documents
Professionnel Documents
Culture Documents
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:
HTML5;
CSS;
JavaScript / jQuery;
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.
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.
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.
1.
Reply
2.
Reply
3.
Reply
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
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
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.
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(
$('#server_parameters').text(data);
5
6
dateFormat = jqXHR.responseJSON.dateFormat;
})
10
11
12
chamado caso a request falhe, e que est sendo chamado aqui de forma
13
14
15
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>
<form id="tela_selecao">
<div class="ui-field-contain">
<label style="margin-top:0">Unidade</label>
10
<b><span id="unidade">Nenhuma</span></b>
11
</div>
12
13
</form>
14
15
16
17
</div>
</div>
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
$('#buscar').on('click', function() {
$.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
18
19
usaremos o mtodo POST. O backend possui outro mtodo justamente para criar o
20
21
$('#criar').on('click', function() {
22
23
postData = $('#tela_selecao').serialize();
24
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() {
$(window).on('keydown', function(event) {
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() {
4
5
});
});
melhor fazer:
JavaScript
$(document).on('pagecreate', '#
$('#botao').click(function() {
// Cdigo do event handler
});
});
$('#botao').click(function() {
4
5
});
});
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;
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)
Sublime Text
Moqups
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() {
5
6
$(this).selectmenu('refresh', true);
});
Lgica de negcio fica no cdigo ABAP, e isso fica no BSP. Falarei disso no prximo post.
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.
Reply
2.
Reply
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
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
<!doctype html>
<html>
<head>
<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>
</head>
10
<body>
11
12
13
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>
<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>
</head>
10
<body>
11
12
13
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:
O fluxo representado por esse diagrama basicamente o que a aplicao BSP deve fazer:
1.
2.
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:
Caractersticas da aplicao
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>
<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>
10
<script src="script.min.js"></script>
11
</head>
12
<body>
13
14
15
</body>
</html>
View
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
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;
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.
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.
METHOD do_request.
2
3
DATA: cdata
TYPE string,
code
TYPE i,
reason
TYPE string.
9
10
11
12
13
14
IF me->view IS INITIAL.
15
16
17
18
19
20
me->call_view( me->view ).
21
22
ELSE.
23
24
25
* s pode ter sido feita via Ajax. Lembram dos exemplos de request
26
27
* assim:
28
29
* main?action=algumaCoisa&...
30
31
32
33
34
35
36
Uma request GET espera uma resposta com dados em algum formato
37
38
39
40
41
42
43
44
45
46
47
48
49
50
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
68
cdata = me->get_...
69
70
71
72
73
74
75
76
77
78
79
me->create_goods_movement(
80
EXPORTING
81
82
IMPORTING
83
ex_cdata
84
ex_content_type = content_type
85
ex_message_type = message_type
86
= cdata
).
87
88
89
90
me->save_inventory_count(
91
EXPORTING
92
93
IMPORTING
94
ex_cdata
95
ex_content_type = content_type
96
ex_message_type = message_type
97
= cdata
).
98
99
100
101
me->set_...(
102
103
WHEN OTHERS.
104
105
Neste caso temos uma request Ajax sem o atributo action, ou seja,
106
107
108
109
cham-la novamente:
110
111
me->call_view( me->view ).
112
RETURN.
113
114
ENDCASE.
115
116
117
118
* interprete corretamente:
119
120
IF message_type = 'E'.
121
122
123
ELSE.
124
125
reason = 'OK'.
126
ENDIF.
127
128
me->response->set_status(
129
code = code
130
reason = reason
131
).
132
133
134
135
136
137
* handler:
138
139
140
141
142
143
144
145
146
147
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,
message_text
number
plant
storage_location
TYPE string,
TYPE string,
TYPE werks_d,
TYPE lgort_d.
9
10
11
FIELD-SYMBOLS: <field>
TYPE ihttpnvp,
12
13
14
15
16
17
18
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
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
46
* dados:
47
48
ex_cdata = |\{"materials":[|.
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
ENDLOOP.
69
70
71
72
ex_content_type = 'application/json'.
73
74
ELSE.
75
76
77
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.
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!
1.
Reply
2.
Reply
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.
que detalhou a explicao dos parmetros das Tags e colocou ate programas de
Exemplo:
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.