Skip to Content

Synopsis: In this series of Blogs, I’ll explore how the Web Intelligence RESTful Raylight Web Services allow users to automate and simplify the management, modification, creation and updates to a batch of Web Intelligence documents.  This series will be of interest to Web Intelligence administrators, designers, consultants and power users, to save time and effort and get the most out of your investment in Web Intelligence.

Previous Entry: http://scn.sap.com/community/restful-sdk/blog/2013/09/07/scripting-web-intelligence-the-restful-raylight-web-services–learing-it

The Basics

First we’ll cover the basics: logging onto and logging off of Raylight, and loading a Web Intelligence document onto Raylight, and unloading it.


The thing to keep in mind with the Raylight API is that all processing of the Web Intelligence document is done on BI Platform servers.  That means that, if you request a list of WebI documents from Raylight, Raylight accepts that request and queries the Platform Central Management Server (CMS) for the informatoin. 

If you request export of a WebI document, Raylight will send a request to the Web Intelligence Processing Server (WebI PS), that will in turn request file information from the CMS, the CMS will send back the info, then the WebI PS will request the wid file from the File Repository Server (FRS) that will stream it back, and then the WebI PS will open the wid file, generate the export format, then stream it back to Raylight, that will then stream it back to your REST client.

At that point, the wid file will remain open in the WebI PS till you send a request to Raylight to unload the document. 

To be able to do all that, first you need to log onto BI Platform.  Then after you’re done, you need to log off.  So let’s cover that first.

Logon/Logoff

The RESTful API allows for various different ways to authenticate or pass authentication context: (1)  passing a username/password, (2) passing a serialized session or token from a different application already authenticated with Platform, (3) Active Directory Single Sign-On, or (4) Trusted Authentication.   We’ll cover the first option – the other option irequires configuring the RESTful Web Service Provider on Platform as described in the Platform REST Web Services document (http://help.sap.com/businessobject/product_guides/sbo41/en/sbo41_bip_rest_ws_en.pdf).

What you need to do to log on is send a HTTP POST request to the logon URI:

   http://{{hostname}}:{{port}}/biprws/logon/long

where you would replace {{hostname}} and {{port}} with the name of the host and port number where the Platform Web Application Container Service (WACS) on Platform may be contacted.  You would send logon credentials in JSON format in the form:

{
    "userName": "User name",
    "password": "password",
    "auth": "secEnterprise"
}

where “auth” represents the authentication type, “secEnterprise” for Enterprise authentication, “secWinAD” for Windows AD, “secLDAP” for LDAP and “secSAPR3” for SAP.  To specify that we’re sending in the logon credentials in JSON format and that we’d like the response to also be in JSON, we’ll add HTTP Headers:

Accept:  application/json

Content-Type: application/json

Here’s how the request would look like in POSTMAN:


postman_logon.JPGPOSTMAN with RESTful request to log onto Platform REST.

where I’ve defined {{hostname}} and {{port}} as POSTMAN environment variables that I set to correspond to my Platform deployment.

When the request is sent out, what’s returned on unsuccessful logon is:

{
    "error_code": "FWB 00008",
    "message": "Enterprise authentication could not log you on. Please make sure your logon information is correct. (FWB 00008)\n"
}

where “error_code” is the identifier for the error encountered, as described in the Error Message Guide (http://help.sap.com/businessobject/product_guides/sbo41/en/sbo41sp1_error_messages_en.pdf), and the “message” provides greater detail.  Successful logon returns:

{
    "logonToken": "BIPW08R2:6400@{3&2=6882,U3&2v=BIPW08R2:6400,UP&66=60,U3&68=secEnterprise:Administrator,UP&S9=12,U3&qe=100,U3&vz=OJfqdLXfonZpUDdzHPB9XBcl1dNmtyd8wQFwwFV3Nxk,UP}"
}

where “logonToken” represents the unique identifier for the Enterprise Session that is established with BI Platform.  On subsequent requests, you’ll inform Raylight to use the Session you’ve established by always sending the logon token in the HTTP Header X-SAP-LogonToken.

In POSTMAN, you’d manually copy the logon token into the X-SAP-LogonToken header.  If you’re using a scripting language, you’d parse the JSON return for the logonToken, and store it for re-use later.

Microsoft Powershell 4 (http://technet.microsoft.com/en-us/library/hh857339.aspx) particularly makes it simple to work with JSON, since it has functions to automatically translate JSON into Powershell Custom Objects.  Here’s how you’d log on, obtain the logon token, and add it to subsequent HTTP Headers:


$logonInfo = @{}
$logonInfo.userName = "Administrator"
$logonInfo.password = "Password1"
$logonInfo.auth     = "secEnterprise"
$headers = @{"Accept"       = "application/json" ;
             "Content-Type" = "application/json"
            }
$result = Invoke-RestMethod -Method Post -Uri "http://host:port/biprws/logon/long" -Headers $headers -Body (ConvertTo-Json($logonInfo))
if($result.logonToken -ne $null) {
    $logonToken =  "`"" + $result.logonToken + "`""   # Need to surround token by double-quotes
}  else {
    Write-Error "Logon failed: " + (ConvertTo-Json($result))
    exit
}
$headers = @{"X-SAP-LogonToken" = $logonToken ;
             "Accept"       = "application/json" ;
             "Content-Type" = "application/json"
            }

You can see how the JSON being returned by the Invoke-RestMethod is automatically converted into a Powershell object, from which you can retrieve the JSON property logonToken by the property call $return.logonToken.

To log off the Session, you would send a HTTP POST to

    http://{{hostname}}:{{port}}/biprws/logoff

with an empty body and HTTP Header X-SAP-LogonToken to identify the Session you’re trying to log off.   Successful logoff would return a HTTP 200 OK code, and unsuccessful logoff would return a JSON structure containing “error_code” and “message”. 

Powershell code:

$headers = @{ "X-SAP-LogonToken" = $logonToken ;
              "Accept"           = "application/json" ;
              "Content-Type"     = "application/json"
            }
Invoke-RestMethod -Method Post -Uri "http://myhost:6405/biprws/logoff" -Headers $headers

Load/Unload

To have Raylight do any operations on a Web Intelligence document it must first load it into a WebI PS. A WebI doc can be in one of three states in Raylight:

Unused The document is not loaded.
Original The document has been loaded but no modifications have been made, so there would not be any need to save it back to the repository.
Modified The document has been loaded and modifications to it has been made within the WebI PS.  So the document must be saved back to the repository if you want to modifications to persist beyond the session.

To determine the state, the details for any document is retrieved by a HTTP GET sent to:

    http://{{hostname}}:{{port}}/biprws/raylight/v1/documents/{{documentId}}

where {{documentId}} is the SI_ID value for the WebI doc of interest.  

To get the SI_ID value for a WebI doc, the simplest would be to log onto BI launchpad, find the doc, right-click and bring up it’s Properties.  Here’s the ID displayed for the “Charting Samples” sample doc:

charting_samples_property.JPGProperties of “Charting Sample” doc shown in BI launchpad

So the URI for this doc would be http://{{hostname}}:{{port}}/biprws/raylight/v1/documents/5407.  HTTP GET to that URI with Accept Header application/json returns:

{
    "document": {
        "id": 5407,
        "cuid": "AW4AVT1AUhVAogA6P7OQv9c",
        "name": "Charting Samples",
        "folderId": 5385,
        "path": "Public Folders/Web Intelligence Samples/",
        "updated": "2011-08-16T08:20:46.459-07:00",
        "scheduled": false,
        "state": "Unused",
        "createdBy": "Administrator",
        "lastAuthor": "Sam",
        "size": 48152,
        "refreshOnOpen": false
    }
}

where the state is specified by property document.state. 

If I send a HTTP GET to  http://{{hostname}}:{{port}}/biprws/raylight/v1/documents/5407/pages with Accept Header application/pdf, meaning a request to export the “Charting Samples” doc to PDF format, then a subsequent request for the document detail will return:

{
    "document": {
        "id": 5407,
        "cuid": "AW4AVT1AUhVAogA6P7OQv9c",
        "name": "Charting Samples",
        "folderId": 5385,
        "path": "Public Folders/Web Intelligence Samples/",
        "updated": "2011-08-16T08:20:46.459-07:00",
        "scheduled": false,
        "state": "Original",
        "createdBy": "Administrator",
        "lastAuthor": "Sam",
        "size": 48152,
        "refreshOnOpen": false
    }
}

signifying that the document status is now “Original”, meaning that it’s been loaded onto a WebI PS but that no modifications have been made. 

If I had instead, for example, sent a request to refresh the document, by sending a HTTP PUT request to URI

http://{{hostname}}:{{port}}/biprws/raylight/v1/documents/{{documentId}}/parameters, then the document would be modified (since it will contain new data), and document details would be:

{
    "document": {
        "id": 5407,
        "cuid": "AW4AVT1AUhVAogA6P7OQv9c",
        "name": "Charting Samples",
        "folderId": 5385,
        "path": "Public Folders/Web Intelligence Samples/",
        "updated": "2011-08-16T08:20:46.459-07:00",
        "scheduled": false,
        "state": "Modified",
        "createdBy": "Administrator",
        "lastAuthor": "Sam",
        "size": 48152,
        "refreshOnOpen": false
    }
}

and the state is now “Modified”.  If I would then want to Save the document if I want the one stored in the repository to have the updated data.

To Save a Modified document back to the repository, a HTTP PUT method would be called on the URI:

     http://{{hostname}}:{{port}}/biprws/raylight/v1/documents/{{documentId}}

with an empty body.     In Powershell, the Save request will look like:

$headers = @{ "X-SAP-LogonToken" = $logonToken ;
              "Accept"           = "application/json" ;
              "Content-Type"     = "application/json"
              }
$result = Invoke-RestMethod -Method Put -Uri "http://myhost:6405/biprws/raylight/v1/documents/5407" -Headers $headers

and after this request, the document detail will list the status as “Original” again, since the WebI doc loaded in the WebI PS would be in synch with the version stored in the repository.

After you’re done with a document, it’s good practise to unload it from the WebI PS, and put the state back to “Unused” – otherwise, it will take up resources till timeout would automatically unload it from the server.

To explicitly unload it from Raylight, a HTTP PUT method is sent to the document URI with the following JSON body:

{
  "document" : { "state" : "unused" }
}

The Powershell code for the unload document request:

$headers = @{ "X-SAP-LogonToken" = $logonToken ;
              "Accept"           = "application/json" ;
              "Content-Type"     = "application/json"
              }
$result = Invoke-RestMethod -Method Put -Uri "http://myhost:6405/biprws/raylight/v1/documents/5407" -Headers $headers -Body (ConvertTo-Json(@{"document"=@{"state"="Unused"}}))

One has to be a bit careful here – the only difference between a Save document and an Unload document request is the absence or presence of the JSON HTTP Body.  You’d not want to forget the body if all you wanted to do was unload and not save!

Concluding Remarks

Looking back at what I wrote above, I’m thinking well, that’s pretty detailed, verging on the pedantic.  That’s pretty much a fair assessment. 

But I think it well worth going through the above, trying it out in a RESTful Client such as POSTMAN or your preferred scripting language of choice.  It’s really useful to know the document workflow on the server-side as you’re coding against Raylight. 

In fact, if you go back and read the code I posted at the end of the first blog entry I made in this series (http://scn.sap.com/community/restful-sdk/blog/2013/09/05/scripting-web-intelligence-the-restful-raylight-web-services), you’d pretty much understand the workflow now:  (1) logging on, (2) retrieving document detail, (3) refreshing the document data, (4) exporting to PDF, (5) unloading the document, and (6) logging off. 

I promise that, after you’ve grasped the fundamental concepts of document life cycle described above, everything after will be pure gravy – useful functionality and cool tricks!

Next Entry: http://scn.sap.com/community/restful-sdk/blog/2013/09/30/scripting-web-intelligence-the-restful-raylight-web-services–languages-and-content-locale


To report this post you need to login first.

5 Comments

You must be Logged on to comment or reply to a post.

  1. Jan Froehlich

    Great post to understand the document lifecycle with the REST SDK. Thanks Ted.

    And finally good to see that someone at SAP is using JSON with the webservice.

    (0) 
  2. Anthony MULLER

    Hi Michael,

    I agree BO 3.x is vey different than BI4.x.

    You need more documentation about OpenDocument or RESTful WebServices?

    Best regards,

    Anthony

    (0) 
  3. Hayden T

    Thank you so much for this wonderful article.

    This is very helpful.

    I wonder if anyone could help me with 1 question…?

    I did this, but it is returning XML information such as <media>, <style>…

    http://{{hostname}}:{{port}}/biprws/raylight/v1/documents/5407.

    *Of course I set content-type to application/json

    What do you think is the reason behind this…?

    (0) 
    1. Eric FESTINGER

      hello

      Setting “Content-Type:” is related to the payload you are sending along your request, whereas “Accept:” tells the service which media type you are expecting as a response.

      eric

      (0) 

Leave a Reply