We are one step closer to our goal: the seamless integration of Google Wave into SAP Applications
A robot is an automated participant on a wave. A robot can read the contents of a wave in which it participates, modify the wave's contents, add or remove participants, and create new blips and new waves. In short, a robot can perform many of the actions that any other participant can perform
More Infos Google Wave Robots API
But what is now an "active robot"? Until last week it was not possible to manipulate or create waves from outside Google Wave. This has changed with the new Robot API v2:
Robots may not only act as passive entities, responding to events as they occur, but may initiate their own operations as well. The Active Robot API allows robots to send operations to Wave outside of the event-driven model. In particular, this API allows for the following:
More Infos The Active Robot API
First we have to create a regular robot that does ... exactly nothing. We don't want to react on wave changes in this demo. Possible but not necessary.
The robot just creates an instance of itself:
from waveapi import robotfrom waveapi import appengine_robot_runnerif __name__ == '__main__':
bot = robot.Robot('se38xxx', image_url='http://se38xxx.appspot.com/assets/service.png', profile_url='http://se38xxx.appspot.com/')
appengine_robot_runner.run(bot)
The more interesting part is the Post-Handler-Class, where we implement the whole logic:
import cgiimport loggingfrom waveapi
import robotfrom google.appengine.ext
import webappfrom google.appengine.ext.webapp.util
import run_wsgi_appclass
MainPage(webapp.RequestHandler):
__bot = None
def __create_robot(self):
self.__bot = robot.Robot('se38xxx', image_url='http://se38xxx.appspot.com/assets/service.png', profile_url='http://se38xxx.appspot.com/')
CONSUMER_KEY = '493DEMO8625'
CONSUMER_SECRET = 'xmW/6cHk6DEMOwIu1M0poUVd'
self.__bot.setup_oauth(CONSUMER_KEY,
CONSUMER_SECRET, s
erver_rpc_base='http://gmodules.com/api/rpc')
def __add_blip(self):
logging.debug("Add Blip")
waveId = cgi.escape(self.request.get('waveid',
default_value=''))
if waveId == '':
return
waveId = 'googlewave.com!w+' + waveId
waveletId = 'googlewave.com!conv+root'
logging.debug("Fetching wavelet: " + waveId+", " + waveletId)
wavelet = self.__bot.fetch_wavelet(waveId, waveletId)
text = cgi.escape(self.request.get('text',
default_value='No text given'))
wavelet.reply(text)
self.__bot.submit(wavelet)
self.response.out.write('OK Blip created')
def __create_wave(self):
wave_user = cgi.escape(self.request.get('wave_user', default_value='xxx@googlewave.com'))
wavelet = self.__bot.new_wave(domain='googlewave.com',
participants=[wave_user],
message='New message',
submit=True)
title = cgi.escape(self.request.get('title', default_value='No title given'))
wavelet.title = title
wavelet.root_blip.append('This is an Integration Test')
wavelet.root_blip.append_markup('between SAP WDA and Google Wave')
wavelet.reply('And another Blip in Wave ' + wavelet.wave_id)
self.__bot.submit(wavelet)
self.response.out.write('OK ' + wavelet.wave_id)
def post(self):
action = cgi.escape(self.request.get('action', default_value=''))
if action == '':
return
self.__create_robot()
if action == 'new_wave':
self.__create_wave()
if action == 'add_blip':
self.__add_blip()
def main():
application = webapp.WSGIApplication(http://scn.sap.com/people/uwe.fetzer/blog/2010/03/11/wave-islands-in-webdynpro-abap/('/app.*', MainPage), debug=True)
run_wsgi_app(application)
if __name__ == "__main__":
main()
Short explanation
application = webapp.WSGIApplication(http://scn.sap.com/people/uwe.fetzer/blog/2010/03/11/wave-islands-in-webdynpro-abap/('/app.*', MainPage), debug=True)
-> we react on all requests on the path "/app"
CONSUMER_KEY = '493DEMO8625'
CONSUMER_SECRET = 'xmW/6cHk6DEMOwIu1M0poUVd'
-> the OAuth keys we received from the registration of our robot
action = cgi.escape(self.request.get('action', default_value=''))
-> depending on the "action" parameter, we can process "new_wave" or "add_blip" steps. Not an REST interface yet, I know, please no comments on that
Now we can call the Post-Handler from within the WDA application:
METHOD create_wave .
DATA: lr_client TYPE REF TO if_http_client
, lv_content TYPE string
, lo_nd_main TYPE REF TO if_wd_context_node
, lo_el_main TYPE REF TO if_wd_context_element
, ls_main TYPE wd_this->element_main
, lv_title TYPE wd_this->element_main-title
, lv_own_user TYPE wd_this->element_main-own_user
.
"*--- prepare message ---*
cl_http_client=>create(
EXPORTING
host = 'se38xxx.appspot.com'
IMPORTING
client = lr_client
).
lr_client->request->set_header_field(
name = '~request_uri'
value = '/app/'
).
"navigate from <CONTEXT> to <MAIN> via lead selection
lo_nd_main = wd_context->get_child_node( name = wd_this->wdctx_main ).
"get element via lead selection
lo_el_main = lo_nd_main->get_element( ).
"get single attribute
lo_el_main->get_attribute(
EXPORTING
name = `TITLE`
IMPORTING
value = lv_title ).
"get single attribute
lo_el_main->get_attribute(
EXPORTING
name = `OWN_USER`
IMPORTING
value = lv_own_user ).
lr_client->request->set_form_field(
name = 'title'
value = lv_title
).
lr_client->request->set_form_field(
name = 'wave_user'
value = lv_own_user
).
lr_client->request->set_form_field(
name = 'action'
value = 'new_wave'
).
lr_client->request->set_header_field(
name = '~request_method'
value = 'POST'
).
"*--- send ---*
lr_client->send( ).
lr_client->receive( ).
lv_content = lr_client->response->get_cdata( ).
lr_client->close( ).
"*--- store created wave id ---*
DATA: lv_waveid TYPE wd_this->element_main-waveid
, lv_dummy TYPE string
.
"@TODO fill attribute
IF lv_content(2) = 'OK'.
SPLIT lv_content AT '+' INTO lv_dummy lv_waveid.
ENDIF.
"set single attribute
lo_el_main->set_attribute(
name = `WAVEID`
value = lv_waveid ).
ENDMETHOD.
To embedd the wave I have an Iframe on the page which call an BSP (with the received WaveID as parameter):
<%@page language="abap"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<title>Google Wave Embed API Example: Simple Wave</title>
<script src="http://wave-api.appspot.com/public/embed.js" type="text/javascript"></script>
<script type="text/javascript">
function initialize() {
var wavePanel = new WavePanel('https://wave.google.com/wave/');
var uiConfig = new WavePanel.UIConfig();
uiConfig.setFooterEnabled(true);
uiConfig.setHeaderEnabled(true);
uiConfig.setToolbarEnabled(true);
uiConfig.setBgcolor('#FFF');
uiConfig.setColor('#000');
uiConfig.setFont('verdana');
uiConfig.setFontSize('12px');
wavePanel.setUIConfigObject(uiConfig);
wavePanel.loadWave('googlewave.com!w+<%= waveid %>');
wavePanel.init(document.getElementById('waveframe'));
}
</script>
</head>
<body onload="initialize()">
<div id="waveframe" style="width: 100%; height: 400px"></div>
</body>
</html>
As I have described in the timline, the only missing part is the hook back from wave to the WDA application. But Thomas J. promissed it will be part of NW 7.02 (or 7.03?)
Now it's your turn. What can we do with this solution?
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
4 | |
3 | |
3 | |
2 | |
2 | |
2 | |
2 | |
1 | |
1 | |
1 |