Friday, 21 October 2011

Making OBIEE web service friendly


I know that I am obsessed with web services, but this is my final article in the series dealing with web services.

There are a few open areas in this topic and I don’t think there is an immediate solution to them. I will be on the lookout for the solutions of these problems and will update this article when I find the solutions

Let me 1st describe my intent here. I am trying to jot down a mechanism to call web services from OBIEE without the need to change the repository.  In one of my previous posts, we have seen the mechanism to invoke web services from a PL SQL function, but calling a PL SQL function will entail a change in the repository to accommodate it. Changing the repository for this purpose is obviously not a good idea because repository is exclusively meant for metadata.

The code in this article helps us call a web service from java script which gives us a lot of flexibility because java script can easily be invoked from a lot of places like the narrative view, dashboard etc.

Following are a few obvious uses of this approach and I am sure you can list more.
        1.        Trigger a BPEL work flow when the user clicks on certain link.
        2.        Perform actions in other applications which are related to some action taken by the user in OBIEE.
        3.        Invoke custom web services, created in BPEL. These custom BPEL web services can easily do all kinds of operations like fetching something from the data base and reading something from a file using file adapters.
I have not put an example for file adapters but using file adapters in BPEL is as easy as using database adapters.
Again JMS adapter and Java web service adapter can help us integrate OBIEE with java code.
        4.        There is a mechanism to do seamless navigation between OBIEE and BI Publisher, but this is another way in which you can schedule reports in BI Publisher from OBIEE, without actually leaving the OBIEE’s portal

Alright, some bad news now
Problem 1:
This mechanism only works within the domain. If you put this code outside the OBIEE server, this piece of code will not work unless a parameter called Access-Control-Allow-Origin is set to accept the web service requests. By default OC4J does not accept cross domain requests, and unfortunately I could not find the place in OC4J where this parameter could be set. I will be on the lookout for this and will let you know when I find a solution.
There are a number of claims about a work around to this problem using Jquery+JSONP. Somehow it didn’t work for me and I will have to continue my work on this. Again I fail to understand, how JSONP can make a request when the server is not ready to accept it.

There is one possible cheap solution to this problem.

         1.        Put a file in the domain in which the web service exists
         2.        Put the java script code, to call the web service, in this file
         3.        Make an http request to this file from any other domain

This solution is cheap because it screws your cross domain security. The best method will be to find Access-Control-Allow-Origin parameter and set it to accept requests from the domain from which you intend to send them.
Problem 2:
Well this one is not exactly a problem. We have to create an object to send the request and the object we create depends on the browser we use. If your client works with multiple browsers then you will have to search the documentation for your browser, to find the object, to be created for that browser
In case of Mozilla firefox, the class of the object is XMLHttpRequest

Now the solution:

We are calling the BI Publisher’s web service from OBIEE and both of these are hosted on the same OC4J instance so we do not have a domain problem for this example
We are invoking getFolderContents function of the PublicReportService and I have hardcoded the name of a folder in my soap envelope. It is easy to change these values dynamically depending on the link the user clicks, using the narrative view.
If the Access-Control-Allow-Origin parameter was set then it would have appeared in the response headers in the screenshot below.

  











 Let’s look at the code for generating this. Remember, this will only work with Mozilla. You will have to change XMLHttpRequest to something else to suit a different browser

<script language="Javascript">
function asd ()
{
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("POST", "http://vpatha-lap:9704/xmlpserver/services/PublicReportService_v11",true);
xmlhttp.setRequestHeader("Content-Type","text/xml; charset=utf-8");
xmlhttp.setRequestHeader("SOAPAction","getFolderContents");
xmlhttp.onreadystatechange=function (){   
       if (xmlhttp.readyState ==4 && xmlhttp.status == 200){
            var xmlDoc=xmlhttp.responseXML ;
            var Xml2String;
            if (xmlDoc.xml) {
                Xml2String=xmlDoc.xml
            }else{
                Xml2String= new XMLSerializer().serializeToString(xmlDoc);
            }
           var msg= "RESPONSE HEADERS *********\n";
           msg+=xmlhttp.getAllResponseHeaders();
           msg+="Response here *******************\n";
           msg+= Xml2String;
           msg+="\nResponse ends here ****************";
            alert( msg );         
       }
    }
var xml = '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" '
 + ' xmlns:pub="http://xmlns.oracle.com/oxp/service/v11/PublicReportService" '  
+ 'xmlns:pub1="http://xmlns.oracle.com/oxp/service/PublicReportService"> <soapenv:Header/> '
+  ' <soapenv:Body> <pub:getFolderContents> ' 
+ ' <pub:folderAbsolutePath>/Marketing</pub:folderAbsolutePath> '
+ ' <pub:userID>Administrator</pub:userID> <pub:password>Administrator</pub:password> ' 
+ '</pub:getFolderContents> </soapenv:Body> </soapenv:Envelope> ' ;
xmlhttp.send(xml);
}
</script>
<html>
  <head>
    <title>Web services</title>
</head>
<form>
 <table>
    <tr>
      <td> <input value="Click for response" type="button" onclick="Javascript:asd();"></td>
    </tr>
 </table>
</form>
</body>
</html>

No comments: