Sunday, 18 November 2012

OBIEE data extract using SSIS

 OBIEE & SSIS :


This post is in continuation to my previous post(http://obieevbdotnet.blogspot.jp/) where we have learn how to retrive xml data for a OBIEE query using web services. 

PROBLEM STATEMENT:

It is simple to extract xml output for a single OBIEE query however if we need output for multiple queries and want to schedule a query, we need a scheduler to control and extract the output.

SOLUTION STATEMENT:

I have used SQL server integration services(SSIS) to schedule and extract OBIEE output to a shared drive. This implementation consists of 2 main steps:
  1. Create a local web services using the class defined in my previous post.
  2. Call the local web services from SSIS package.
  3. Build and schedule a job to call the package in SQL server.
You can find the explaination for step 1 & 2 below



STEP 1: Create a local web services using the class defined in my previous post.

  • Create a new asp.net web service project.
  • Add a web service template or rename the existing web service template as "webservice.asmx".
  • Paste below code in "webservice.vb"
Public Class webserviceInherits System.Web.Services.WebService
Dim obj As New obiee   ' Refer the post http://obieevbdotnet.blogspot.jp/ for obiee class

<WebMethod()> _
Public Function RunReportPathSiebel(ByVal REPORTID As String, ByVal REPORTPATH As String) As String
Dim temp As String = ""
Try
     obj.repId = REPORTID
     obj.ExecuteQueryPath(REPORTPATH)      ' executequery method will extract the xml data file in C:\temp folder
Catch ex As Exception
     temp = ex.Message
End Try

Return temp
End Function

End Class
  • Debug and Test the webservice.
  • Execute "RunReportPathSiebel"  by supplying "reportid" and "reportPath" as below


STEP 2: Call the local web services from SSIS package.

Any web services can be call directly from SSIS using "WEB Service Task" and use the method available, however there is one limitation of using it. Web service task need "HTTP connection Manager" setting to connect the WSDL(web service description language) specification of the web service. I am assuming that our OBIEE query is a long running query and hence the "Time Out" setting in connection manager is limited i.e 300 sec. which is very less.


I am going to show you an alternative method i.e using "SCRIPT Task" in SSIS.

  • Open BID studio for SQL server 2005/2008 or higher.
  • Create a new Integration Services Project and open package.dtsx
  • Add a Script Task by dragging from the toolbox.
  • Set the properties of Script Task as below
  • Click "Design Script" to open visual studio editor.
  • Paste the below class outside the main class i.e "ScriptMain". WS class will connect your local web services and execute a specific method.
Public Class WSPublic Function CallWebService(ByVal webServiceAsmxUrl As String, _
ByVal serviceName As String, ByVal methodName As String, _
ByVal args() As Object) As Object
Try
Dim client As System.Net.WebClient = New System.Net.WebClient()
'-Connect To the web service
Dim stream As System.IO.Stream = _
client.OpenRead(webServiceAsmxUrl + "?wsdl")
'Read the WSDL file describing a service.
Dim description As ServiceDescription = ServiceDescription.Read(stream)
'LOAD THE DOM'''''''''''''''''''''''''''
'--Initialize a service description importer.
Dim importer As ServiceDescriptionImporter = New ServiceDescriptionImporter()
importer.ProtocolName = "Soap12" ' Use SOAP 1.2.
importer.AddServiceDescription(description, Nothing, Nothing)
'--Generate a proxy client.
importer.Style = ServiceDescriptionImportStyle.Client
'--Generate properties to represent primitive values.
importer.CodeGenerationOptions = System.Xml.Serialization.CodeGenerationOptions.GenerateProperties
'Initialize a Code-DOM tree into which we will import the service.
Dim nmspace As CodeNamespace = New CodeNamespace()
Dim unit1 As CodeCompileUnit = New CodeCompileUnit()
unit1.Namespaces.Add(nmspace)
'Import the service into the Code-DOM tree.
'This creates proxy code that uses the service.
Dim warning As ServiceDescriptionImportWarnings = _
importer.Import(nmspace, unit1)
If warning = 0 Then
'--Generate the proxy code
Dim provider1 As CodeDomProvider = _
CodeDomProvider.CreateProvider("VB")
'--Compile the assembly proxy with the // appropriate references
Dim assemblyReferences() As String
assemblyReferences = New String() {"System.dll", _
"System.Web.Services.dll", "System.Web.dll", _
"System.Xml.dll", "System.Data.dll"}
Dim parms As CompilerParameters = New CompilerParameters(assemblyReferences)
parms.GenerateInMemory = True
Dim results As CompilerResults = provider1.CompileAssemblyFromDom(parms, unit1)
'-Check For Errors
If results.Errors.Count > 0 Then
Dim oops As CompilerError
For Each oops In results.Errors
System.Diagnostics.Debug.WriteLine("========Compiler error============")
System.Diagnostics.Debug.WriteLine(oops.ErrorText)
Next
Throw New System.Exception("Compile Error Occurred calling webservice.")
End If
'--Finally, Invoke the web service method
Dim wsvcClass As Object = results.CompiledAssembly.CreateInstance(serviceName)
Dim mi As MethodInfo = wsvcClass.GetType().GetMethod(methodName)
Return mi.Invoke(wsvcClass, args)
Else
     Return Nothing
End If
Catch ex As Exception
     Throw ex
End Try
End Function
End
Class
  • Copy and paste the code for the main class.
Public Class ScriptMain
 Public Sub Main()
        'Local web services URL
        Dim WebserviceUrl As String = "http://localhost/OBIDEX_SERVICE/OBIEE_Service.asmx"
        'specify service name
        Dim serviceName As String = "OBIEE_Service"
        'specify method name to be called
        Dim methodName As String = "RunReportPathSiebel"
        'Arguments passed to the method
        Dim arArguments(1) As String

        'Our web service has two parameters ReportID and ReportPath in OBIEE
        arArguments(0) = "reportname"
        arArguments(1) = "/users/userid/foldername/reportname"
        Dim objCallWS As New WS
        Dim sSessionId As String

        sSessionId = CStr(objCallWS.CallWebService(WebserviceUrl, serviceName, methodName, arArguments))
        'MsgBox("new SessionID: " & sSessionId)
  Dts.TaskResult = Dts.Results.Success
 End Sub
End Class

  • Debug and run the script task.





Good Luck !!
RSingh

Wednesday, 14 November 2012

Asyncronous Data Extraction from OBIEE 10g using WEB service


PROBLEM STATEMENT :

Few months ago i was able to extract xml data from OBIEE and download it in a shared drive for further use. However the query which i am using was a simple query that extract few rows and not a complex queries i.e queries that does not take much time(say 2-3 min) to execute. Very ofter i got an error message "Query Time Out" at the calling portion of the web application. I have posted few queries on OBIEE blog and did try to take help from the experts but did not get the right solution what i am looking for.

I am sure that this post will help for those friends who are trying to integrate with web(.net) or develop a system for extracting or displaying data out of OBIEE by using queries that is taking long time to execute.

SOLUTION STATEMENT :

Asyncronous Call ! Now i am going to show how we can call OBIEE executeXMLQueryAsync  Method of XMLviewservice. Dot Net provides us the functionality to implement Asyncronous Call i.e waiting long running task to complete without interrupting the main thread. When the task got completed the event handler automatically transfer the control to an address where we actually need to download or extract the information received from OBIEE.



Step 1 - Add OBIEE web services as a web reference using asp.net




Step 2 - Add a Class file into the project & Paste the following Source Code


Imports saw = OBIDownloader.obieesms  ' OBIDownloader is the name of the project & "obieesms" web reference name.
Imports System.Xml
Imports System.Xml.Schema
Imports System.IO
Imports System.Threading
Imports System.Data
Imports System.net
Imports System.Web
Imports System.Web.Services
Public Class obiee
    Dim xmlviewservice As New saw.XmlViewService  ' Creating xmlviewservice object for accessing executeXML method

     'Below declaration are important parameters for executeXML method
    Dim repref As New saw.ReportRef()
    Dim reportparams As New saw.ReportParams
    Dim xmlQueryExecutionOption As New saw.XMLQueryExecutionOptions
    Dim QueryResult As New saw.QueryResults

    'Declaring SessionID variable
    Public sessionid As String


    'Other variable declaration
    Public qid As String
    Dim rstring As String = ""
    Private repPath As String
    Public repId As String
    Public ds As New DataSet

    'XML and XSD export Path, Please create a temp folder in C drive.
    Dim tempPath As String = "C:\temp\"

    Dim App_Path As String = tempPath
    Private xmlPath As String = tempPath
    Private xsdPath As String = tempPath
    Public exportPath As String = tempPath
    Private colCount As Integer

'*************************************************************************
    'Below procedure call executeXMLquery by supplying "reportPath". Note the report path need to be copy from OBIEE.
'*************************************************************************
    Public Sub ExecuteQueryPath(ByVal reportPath As String)
        repPath = reportPath
        repref.reportPath = repPath
        Try

            xmlQueryExecutionOption.async = True
            xmlQueryExecutionOption.maxRowsPerPage = 500
            xmlQueryExecutionOption.refresh = True
            xmlQueryExecutionOption.presentationInfo = True

            'Declaring Asyncronous Event Handler, Transfer of control will redirect to "Extracting" procedure upon completion of the event.
            AddHandler xmlviewservice.executeXMLQueryCompleted, AddressOf Me.Extracting

            'Retriving schema file i.e xsd containing datatypes and columns
            QueryResult = xmlviewservice.executeXMLQuery(repref, saw.XMLQueryOutputFormat.SAWRowsetSchema, xmlQueryExecutionOption, reportparams, sessionid)
            'Saving schema file
            CreateXSD(QueryResult.rowset)

            'Asyncronous executeXML query method for retriving xml data file using sessionid
            xmlviewservice.executeXMLQueryAsync(repref, saw.XMLQueryOutputFormat.SAWRowsetData, xmlQueryExecutionOption, reportparams, sessionid)
        Catch ex As Exception
            'dobj.UpdateStatus(repId, "N", ex.Message & Chr(10) & "Module ExecuteQueryPath")
        End Try
    End Sub


'*************************************************************************
'Below procedure is call back when executeXMLquery is completed
'*************************************************************************
    Sub Extracting(ByVal sender As Object, ByVal e As saw.executeXMLQueryCompletedEventArgs)
        Try
            QueryResult = e.Result
            qid = QueryResult.queryID
            Dim flag As Integer = 0
            Dim nstring As String = ""
            If Trim(QueryResult.rowset) <> "" Then
                rstring = "<?xml version='1.0' ?>" & Chr(10) & QueryResult.rowset
                rstring = Replace(rstring, "</rowset>", "")
                nstring = rstring
                flag = 1
            Else
                nstring = ""
                flag = 0
            End If
            Dim count As Integer = 2
            Do While Not QueryResult.finished
                count = count + 1
                QueryResult = xmlviewservice.fetchNext(qid, sessionid)
                qid = QueryResult.queryID
                If flag = 0 And Trim(QueryResult.rowset) <> "" Then
                    rstring = "<?xml version='1.0' ?>" & Chr(10) & QueryResult.rowset
                    rstring = Replace(rstring, "</rowset>", "")
                    flag = 1
                Else
                    rstring = QueryResult.rowset
                    rstring = Replace(rstring, "<rowset xmlns=""urn:schemas-microsoft-com:xml-analysis:rowset"" >", "")
                    rstring = Replace(rstring, "</rowset>", "")
                End If
                nstring = nstring & rstring
            Loop
            nstring = nstring & "</rowset>"
            'Saving XML data file
            CreateXML(nstring)
            Dim s As New saw.SAWSessionService
            s.logoff(sessionid)
            s.Dispose()
        Catch ex As Exception
            'dobj.UpdateStatus(repId, "N", ex.Message & Chr(10) & "Module Extracting")
        End Try
    End Sub
'*************************************************************************

    Public Sub CreateXSD(ByVal strs As String)
        rstring = "<?xml version='1.0' ?>" & Chr(10) & strs
        rstring = Replace(rstring, "<rowset xmlns=""urn:schemas-microsoft-com:xml-analysis:rowset"" >", "")
        rstring = Replace(rstring, "</rowset>", "")
        Dim Apath As String = xsdPath
        Apath = Apath & repId & ".xsd"
        Try
            Dim reader As New StringReader(rstring)
            Dim myschema As XmlSchema = XmlSchema.Read(reader, AddressOf ValidationCallback)
            Dim file As FileStream = New FileStream(Apath, FileMode.Create, FileAccess.ReadWrite)
            Dim xwriter As XmlTextWriter = New XmlTextWriter(file, New UTF8Encoding())
            xwriter.Formatting = Formatting.Indented
            myschema.Write(xwriter)
            xwriter.Close()
            reader.Close()
        Catch e As Exception
            'dobj.UpdateStatus(repId, "N", e.Message & Chr(10) & "Module CreateXSD")
        End Try
    End Sub

 '*************************************************************************

    Public Sub CreateXML(ByVal nstring As String)
        Dim Apath As String = xmlPath
        Apath = Apath & repId & ".xml"
        Try
            Dim TextFile As New StreamWriter(Apath, False, System.Text.Encoding.Unicode)
            TextFile.WriteLine(nstring)
            TextFile.Close()
        Catch e As Exception
            'dobj.UpdateStatus(repId, "N", e.Message & Chr(10) & "Module CreateXML")
        End Try
    End Sub

 '*************************************************************************

     Public Sub LogOFF(ByVal saw As saw.SAWSessionService)        saw.logoff(sessionid)
    End Sub

 '*************************************************************************


    Public Sub New()
        Dim saw As New obieesms.SAWSessionService
        sessionid = saw.logon("UserID", "Password")
    End Sub
End Class



Step 3 - Using the obiee.vb class created above. Add a Server side button and paste the following code.

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
     Dim obj As New obiee
     obj.repid = "reportname"
     obj.ExecuteQueryPath("/userid/foldername/reportname")

End Sub

Step 4 - Debug and run the project. You will be receiving an XML file and XSD file in "C:\temp\" folder.





 Good Luck !
RSingh