Friday 31 January 2014

Consuming OBIEE 11g Web Services using Java


We will talk about consuming OBIEE 11g webservices using Java in this article. My previous articles have been about consuming webservices using JavaScript and consuming webservices using PL/SQL. This is my first on consuming webservices using Java. 
My book also has a number of recipes about consuming and creating web services. Check out a brief description of the book and the table of contents. You may also check out the online application build on top of the discussions in the sample chapter of my book.

The prerequisite for this article is Oracle JDeveloper Studio Edition Version 11.1.1.7.0. Download it from http://www.oracle.com/technetwork/developer-tools/jdev/downloads/jdeveloper11117-1917330.html

We will learn to create iBots (Agents) using webservices in this article. Let us see the process.

1. Open JDeveloper and hit the Create button to create a Generic Application as shown below.
2. I call it OBIEEiBotApp.
3. Create a Project in this Application, as shown below. Do not select anything in the shuttle.
4. Right click on the newly created project and select Web Service Proxy.
5. Select JAX-RPC Web Logic Style radio button in Step 2 of Create Web Service Proxy wizard. Enter your webservice WSDL url in step 3 of this wizard. The URL has the following format
http://<webserver>:<port>/analytics/saw.dll?wsdl
6. Select SAWSessionService in step 4 of the wizard and click the Finish button. This service will help us to create an OBIEE session which can then be used with any operation using Webservice.
7. Repeat steps 4 to 6 but select IBotService in step 6 instead of SAWSessionService. We are selecting the IBotService because we plan to create iBots using Webservices in this article.
Your application will now look like the following
8. Right click on oracle.bi.webservices and click the New... button. Create a new Java Class as shown below.
9. Give a name to your class, make the selections as shown in the screenshot below and click OK.
10. Your class will look like the following. You may remove the statement that creates an iBotClass object as we don't really need this. You won't get an error even if this statement isn't removed.
11. Now, we need a few classes for our code so we are going to import them. Put the following import statements right after the package statement.

import webservices.bi.oracle.v6.Logon;
import webservices.bi.oracle.v6.LogonResult;
import webservices.bi.oracle.v6.SAWSessionServiceSoapPortClient;
import webservices.bi.oracle.v6.WriteIBot;
import webservices.bi.oracle.v6.ACL;
import webservices.bi.oracle.v6.AccessControlToken;
import webservices.bi.oracle.v6.Account;
import webservices.bi.oracle.v6.CatalogObject;
import webservices.bi.oracle.v6.IBotServiceSoapPortClient;
import webservices.bi.oracle.v6.ItemInfo;
import webservices.bi.oracle.v6.WriteIBotResult;
import webservices.bi.oracle.v6.ItemInfoType;
import webservices.bi.oracle.v6.NameValuePair;

12. We now have to create a OBIEE session so we create a Logon object and pass it to a SAWSessionServiceSoapPortClient object. The following code does this for us. Put this code in the main method of your class. Code from this point on will go in the main method only.

Dont forget to put replace your username, password, webserver ip and port in the following code.

    Logon my_logon = new Logon();
    my_logon.setName("<username>");
    my_logon.setPassword("<password>");
    LogonResult logResult = new LogonResult();
    String log_sessid = "";
    try {
      SAWSessionServiceSoapPortClient new_soap_port_client =
        new SAWSessionServiceSoapPortClient();
      new_soap_port_client.setEndpoint("http://<webserver>:<port>/analytics/saw.dll?SoapImpl=nQSessionService");
      logResult = new_soap_port_client.logon(my_logon);
      log_sessid = logResult.getSessionID();
      System.out.println(log_sessid);
    } catch (java.lang.Exception e) {
      e.printStackTrace();
    }

13. We now have to create our iBot. To achieve this, we first have to create an object of IBotServiceSoapPortClient class and then call the necessary functions to define the various properties of our iBot. We will need the following classes for this operation.

                a. WriteIBot class :- To set the session id, catalogobject and other such properties.
                b. CatalogObject class :- To define the characteristics of the iBot
                c. ItemInfo class :- To set the caption, creator, last modifier etc.
                d. ItemInfoType class :- Required as an arguement to ItemInfo.setType method.
                e. NameValuePair class :- To set the properties such as the Author
                f. Account class :- Object of this class defines a OBIEE account that does the necessary operation.

Let us now look at the code. The entire code will follow the code written in step 12 above.

    try {
      System.out.println(log_sessid);

      //****************************Object creations************************************

      boolean resolveLinksFlag = false;
      boolean allowOverwriteFlag = false;
      IBotServiceSoapPortClient ibotClient = new IBotServiceSoapPortClient();
      WriteIBotResult ibotResult = new WriteIBotResult();
      WriteIBot ibotObj = new WriteIBot();
      CatalogObject catObj = new CatalogObject();
      ItemInfo itemInfObj = new ItemInfo();
      ItemInfoType itemInfTypObj = ItemInfoType.object;
      NameValuePair[] itemProperties = new NameValuePair[1];
      itemProperties[0] = new NameValuePair();
      //********************************************************************************

//********************Will use this for Item Object**************************************
      itemProperties[0].setName("Author");
      itemProperties[0].setValue("weblogic");
      //********************************************************************************

//********************Used to set the account that creates the iBot*************************

      Account accObj = new Account();
      accObj.setName("weblogic");
      accObj.setAccountType(0);
      //********************************************************************************

//*Setting of the properties of the iBot. Decides the values for each of the iBot tabs in OBIEE portal*
      catObj.setCatalogObject("<?xml version=\"1.0\"?><saw:ibot xmlns:saw=\"com.siebel.analytics.web/report/v1.1\" version=\"1\" priority=\"normal\" xmlns:cond=\"com.oracle.bi/conditions/v1\" xmlns:sawx=\"com.siebel.analytics.web/expression/v1.1\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" jobID=\"9\"><saw:schedule><saw:start startImmediately=\"false\" date=\"2013-12-10\" time=\"04:15:00\"/><saw:recurrence runOnce=\"true\"/></saw:schedule><saw:dataVisibility type=\"runAsUser\" runAs=\"weblogic\" runAsGuid=\"256A12F0A11511E28F457FA5CCEDA162\"/><cond:condition/><saw:choose><saw:when condition=\"true\"><saw:deliveryContent disposition=\"deviceDefault\"><saw:headline><saw:caption><saw:text>Test7</saw:text></saw:caption></saw:headline><saw:reportRef path=\"/shared/2. Functional Examples/Examples/Indexing/Indexing\"/></saw:deliveryContent><saw:postActions/></saw:when><saw:otherwise><saw:postActions/></saw:otherwise></saw:choose><saw:deliveryDestinations><saw:destination category=\"dashboard\"/><saw:destination category=\"activeDeliveryProfile\"/></saw:deliveryDestinations><saw:recipients specificRecipients=\"true\" subscribers=\"false\" customize=\"false\"><saw:specificRecipients><saw:user name=\"weblogic\" guid=\"256A12F0A11511E28F457FA5CCEDA162\"/></saw:specificRecipients><saw:subscribers/></saw:recipients><saw:emailRecipients><saw:emailRecipient address=\"vishal.pathak@cognizant.com\" type=\"HTML\"/></saw:emailRecipients></saw:ibot>");
      //********************************************************************************

//***************************Setting of iBot properties*********************************

      itemInfObj.setCaption("newBot2");

      itemInfObj.setType(itemInfTypObj);


      itemInfObj.setAttributes(0);

      itemInfObj.setCreator(accObj);
      itemInfObj.setLastModifier(accObj);
      //********************************************************************************

//************************ACL related code******************************************

      ACL aclObj = new ACL();
      AccessControlToken[] acTokenObj = new AccessControlToken[1];
      acTokenObj[0] = new AccessControlToken();
      Account accObjForToken = new Account();
      accObjForToken.setName("BIAdministrator");
      accObjForToken.setAccountType(4);
      accObjForToken.setGuid("BIAdministrator");

      acTokenObj[0].setAccount(accObjForToken);

      acTokenObj[0].setPermissionMask(65535);

      aclObj.setAccessControlTokens(acTokenObj);


      itemInfObj.setAcl(aclObj);

      //********************************************************************************

//*********************Setting of a few more iBot properties******************************

      itemInfObj.setOwner(accObj);

      itemInfObj.setItemProperties(itemProperties);


      catObj.setItemInfo(itemInfObj);


      ibotObj.setPath("/shared/newBot2");

      ibotObj.setResolveLinks(resolveLinksFlag);
      ibotObj.setAllowOverwrite(allowOverwriteFlag);
      ibotObj.setSessionID(log_sessid);

      ibotObj.setObj(catObj);


      ibotResult = ibotClient.writeIBot(ibotObj);

      System.out.println(ibotResult.toString());
    } catch (java.lang.Exception e) {
      e.printStackTrace();
    }

While the rest of the code is intuitive, I wish to talk about the argument of catObj.setCatalogObject method. This argument is more or less the definition of our iBot object. Have a look at the screenshot below.
Let me also share a screenshot of the typical ibot to draw a comparison between the XML and the iBot feature on the OBIEE portal.
The XML arguement starts with declaring some namespaces. This is followed by the <saw:ibot> tag at the top. It is important to note that the tags in the XML closely correlate the tabs in the screenshot of a typical iBot.
For example, <saw:ibot> tag is followed by <saw:schedule> tag to set the schedule of the iBot. The screenshot shows a Schedule tab as well. This Schedule tab is used for scheduling the iBot through the OBIEE portal.
Similarly, we also have <cond:condition>, <saw:deliveryDestinations>, <saw:recipients>. These perform similar functions as their corresponding tabs.

We can now right click on the class we just created and then select the Run button.
You will get the following result. Check the highlighted part of the bottom of the screenshot below. It shows the OBIEE session id which was used to create the ibot and the result stored in ibotResult object.
You can now login to the screen and find your iBot.

Till next time :-)

7 comments:

prabu said...

HI Vishal,

Nice documentation.. Easy to understand.. i got one error while following ur steps. can't able to resolve.


java.rmi.RemoteException: SOAPFaultException - FaultCode [{http://schemas.xmlsoap.org/soap/envelope/}Server] FaultString [Authentication error. Invalid session ID or Session Expired] FaultActor [null] Detail [
IAI2Z2JJ
Authentication error. Invalid session ID or Session Expired
project/websubsystems/soapservicesimpl.cpp
202

saw.soap.makesession
saw.SOAP
saw.httpserver.request.soaprequest
saw.rpc.server.responder
saw.rpc.server
saw.rpc.server.handleConnection
saw.rpc.server.dispatch
saw.threadpool.socketrpcserver
saw.threads


]; nested exception is:
weblogic.wsee.jaxrpc.soapfault.WLSOAPFaultException: Authentication error. Invalid session ID or Session Expired
at webservices.bi.oracle.v6.IBotServiceSoap_Stub.writeIBot(IBotServiceSoap_Stub.java:87)
at webservices.bi.oracle.v6.IBotServiceSoapPortClient.writeIBot(IBotServiceSoapPortClient.java:137)
at oracle.bi.webservices.v6.IBotClass.main(IBotClass.java:105)
Caused by: weblogic.wsee.jaxrpc.soapfault.WLSOAPFaultException: Authentication error. Invalid session ID or Session Expired
at weblogic.wsee.codec.soap11.SoapCodec.decodeFault(SoapCodec.java:357)
at weblogic.wsee.ws.dispatch.client.CodecHandler.decodeFault(CodecHandler.java:118)
at weblogic.wsee.ws.dispatch.client.CodecHandler.decode(CodecHandler.java:103)
at weblogic.wsee.ws.dispatch.client.CodecHandler.handleFault(CodecHandler.java:91)
at weblogic.wsee.handler.HandlerIterator.handleFault(HandlerIterator.java:309)
at weblogic.wsee.handler.HandlerIterator.handleResponse(HandlerIterator.java:269)
at weblogic.wsee.ws.dispatch.client.ClientDispatcher.handleResponse(ClientDispatcher.java:213)
at weblogic.wsee.ws.dispatch.client.ClientDispatcher.dispatch(ClientDispatcher.java:150)
at weblogic.wsee.ws.WsStub.invoke(WsStub.java:87)
at weblogic.wsee.jaxrpc.StubImpl._invoke(StubImpl.java:341)
at webservices.bi.oracle.v6.IBotServiceSoap_Stub.writeIBot(IBotServiceSoap_Stub.java:82)
... 2 more

host name and port numbers were correct.

Regards,
Prabu N

Vishal Pathak said...

Hi Prabhu,

Thanks for the comments. The error looks to be with the expiry of your session. Check the server settings.

Regards,
Vishal

Unknown said...

I have the same issue too... Were you able to resolve it? Please share the resolution

ajmald said...

Hi Vishal !!

Thanks a lot, great tutorial, works fine on obiee 11g !

Vishal Pathak said...

You can only do the operations that OBIEE web services let you perform. Check the documentation to find a method that let you do the task you want to do.

Ashvin said...

Hi Vishal,

Great document thanks a lot for it. I am Ashwin from Hyderabad, India. I am also an OBIEE&Informatica developer. Could you please let me know your email address so that I can send you few issues which we do have in BI Publisher and OBIEE. If you can also provide your contact number that would be great.

Thanks

Jyotirmay Nag said...

I am getting the following error when I try to add a new Web Service proxy. OBIEE Version 12.2.1.3.0 and same version JDeveloper.

javax.wsdl.WSDLException: WSDLException: faultCode=PARSER_ERROR: Error reading source with PublicId: null: java.net.UnknownHostException: www.w3.org
at oracle.j2ee.ws.wsdl.xml.WSDLReaderImpl.readWSDL(WSDLReaderImpl.java:380)
at oracle.j2ee.ws.wsdl.xml.WSDLReaderImpl.readWSDL(WSDLReaderImpl.java:331)
at oracle.j2ee.ws.wsdl.xml.WSDLReaderImpl.readWSDL(WSDLReaderImpl.java:315)
at oracle.jdeveloper.webservices.wsdl.CachedWSDLReader.readWSDLInternal(CachedWSDLReader.java:568)
at oracle.jdeveloper.webservices.wsdl.CachedWSDLReader.readWSDL(CachedWSDLReader.java:521)
at oracle.jdeveloper.webservices.wsdl.CachedWSDLReader.readWSDL(CachedWSDLReader.java:492)
at oracle.jdevimpl.webservices.wizard.jaxrpc.common.SpecifyWsdlPanel.fetchWSDL(SpecifyWsdlPanel.java:1062)
at oracle.jdevimpl.webservices.wizard.jaxrpc.common.SpecifyWsdlPanel$1.run(SpecifyWsdlPanel.java:373)
at oracle.ide.dialogs.ProgressBar.run(ProgressBar.java:961)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.net.UnknownHostException: www.w3.org
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:184)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:589)
at java.net.Socket.connect(Socket.java:538)
at sun.net.NetworkClient.doConnect(NetworkClient.java:180)
at sun.net.www.http.HttpClient.openServer(HttpClient.java:463)
at sun.net.www.http.HttpClient.openServer(HttpClient.java:558)
at sun.net.www.http.HttpClient.(HttpClient.java:242)
at sun.net.www.http.HttpClient.New(HttpClient.java:339)
at sun.net.www.http.HttpClient.New(HttpClient.java:357)
at sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(HttpURLConnection.java:1202)
at sun.net.www.protocol.http.HttpURLConnection.plainConnect0(HttpURLConnection.java:1138)
at sun.net.www.protocol.http.HttpURLConnection$6.run(HttpURLConnection.java:1022)
at sun.net.www.protocol.http.HttpURLConnection$6.run(HttpURLConnection.java:1020)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.AccessController.doPrivilegedWithCombiner(AccessController.java:782)
at sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:1019)
at sun.net.www.protocol.http.HttpURLConnection.connect(HttpURLConnection.java:966)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1546)
at sun.net.www.protocol.http.HttpURLConnection.access$200(HttpURLConnection.java:91)
at sun.net.www.protocol.http.HttpURLConnection$9.run(HttpURLConnection.java:1466)
at sun.net.www.protocol.http.HttpURLConnection$9.run(HttpURLConnection.java:1464)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.AccessController.doPrivilegedWithCombiner(AccessController.java:782)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1463)
at java.net.URL.openStream(URL.java:1045)
at oracle.xml.parser.v2.XMLReader.openURL(XMLReader.java:2929)
at oracle.xml.parser.v2.XMLReader.pushXMLReader(XMLReader.java:351)
at oracle.xml.parser.v2.NonValidatingParser.pushExternalDTD(NonValidatingParser.java:784)
at oracle.xml.parser.v2.NonValidatingParser.parseDoctypeDecl(NonValidatingParser.java:658)
at oracle.xml.parser.v2.NonValidatingParser.parseProlog(NonValidatingParser.java:458)
at oracle.xml.parser.v2.NonValidatingParser.parseDocument(NonValidatingParser.java:416)
at oracle.xml.parser.v2.XMLParser.parse(XMLParser.java:251)
at oracle.xml.jaxp.JXDocumentBuilder.parse(JXDocumentBuilder.java:175)
at oracle.j2ee.ws.wsdl.xml.WSDLReaderImpl.readWSDL(WSDLReaderImpl.java:375)
... 9 more