title: HtmlViewService in OBIEE Web Service API is not rendering report (it's only showing spinning loader)
body: <p>I have a Java application that leverages the OBIEE Web Service API to consume data from the BI Server. I am able to XMLViewService and the WebCatalogService just fine, but I can't quite get the HtmlViewService to properly render a report in the Java app. The report just shows the spinning loader, but never actually renders the report. I'm pretty sure it has to do with the fact that the Java app and the BI Server are on different domains. This is what the API documentation says:</p>
  
  <p><strong>In situations where Oracle BI Web Services and the third-party Web server do not  belong to the same Domain Name Service (DNS) domain, users may get JavaScript errors related to browser security constraints for cross-domain scripting. To avoid these issues, use the setBridge() method to modify callback URLs to point to the third-party Web server. Be aware that a Web component executed by the third-party Web server to re-route requests to Oracle BI Web Services is not provided. This function would need to be fulfilled by the third-party application.</strong></p>
  
  <p>Several years ago, I did this same type of integration using .NET/C# and ran in the the same issue because the .NET app and the BI Server were on different domains. As a result, I had to create an HTTP Handler (.ashx file) as well as use the setBridge() method to to solve the issue. </p>
  
  <p>The challenge that I'm having is that I can't find a servlet bridge example for Java. And I'm not too confident in porting the .NET/.ASHX code to a Java servlet/bridge. Does anyone have any code examples or direction they could provide to point me in the right direction?  Here's a snippet of code to show you what I'm doing to pull back the report data:</p>
  
  <pre><code>    // define report path
      ReportRef reportRef = new ReportRef();
      reportRef.setReportPath(reportFolder + "/" + reportName);
  
      // set page params
      StartPageParams pageParams = new StartPageParams(); 
      pageParams.setDontUseHttpCookies(true);
  
      // set report params
      String pageId = htmlService.startPage(pageParams, sawSessionId);
      String reportId = pageId + reportName;
      htmlService.addReportToPage(pageId, reportId, reportRef, null, null, null, sawSessionId);
  
      // get report html
      StringBuffer reportHtml = new StringBuffer(); 
      reportHtml.append(htmlService.getHtmlForReport(pageId, reportId, sawSessionId)); 
  
      // return html
      return reportHtml.toString();
  </code></pre>
  
  <p><strong>This is the error that is coming back in the browser:</strong></p>
  
  <p>XMLHttpRequest cannot load <a href="http://myobiserver.com/analytics/saw.dll?ajaxGo" rel="nofollow">http://myobiserver.com/analytics/saw.dll?ajaxGo</a>. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin '<a href="http://myjavaapp.com" rel="nofollow">http://myjavaapp.com</a>' is therefore not allowed access. </p>
  
  <p>Per requested, here is my .NET/.ASHX bridge:</p>
  
  <pre><code>using System.Collections.Specialized;
  using System.Net;
  using System.Text;
  using System.Web;
  using System;
  using System.Collections;
  using System.Configuration;
  using System.Collections.Specialized;
  using System.Web;
  using System.Text;
  using System.Net;
  using System.IO;
  using System.Diagnostics;
  
  /*
  This is a ASP.NET handler that handles communication 
  between the SharePoint site and OracleBI.
  It will be deployed to: 
  C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\LAYOUTS\OracleBI
  */
  
  public class OracleBridge: IHttpHandler
  {
    public   bool IsReusable {get{return true;}}
    public OracleBridge()
    {
    }
    string getServer()
    {
        string strServer = "http://&lt;enter-domain&gt;/analytics/saw.dll";
       int index = strServer.LastIndexOf("/");//split off saw.dll
       if (index &gt;=0)
          return strServer.Substring(0,index+1);
       else
          return strServer;
    }
    public void ProcessRequest(HttpContext context)
    {
       HttpWebRequest req = forwardRequest(context);
       forwardResponse(context,req);
    }
    private HttpWebRequest forwardRequest(HttpContext context)
    {
       string strURL = makeURL(context);
       HttpWebRequest req = (HttpWebRequest)WebRequest.Create(strURL);
       req.Method = context.Request.HttpMethod;
       NameValueCollection   headers = context.Request.Headers;
       req.Accept  = headers.Get("Accept");
       req.Expect = headers.Get("Expect");
       req.ContentType = headers.Get("Content-Type");
       string strModifiedSince = headers.Get("If-Modified-Since");
       if (strModifiedSince != null &amp;&amp; strModifiedSince.Length != 0)
          req.IfModifiedSince =  DateTime.Parse(strModifiedSince);
       req.Referer = headers.Get("Referer");
       req.UserAgent = headers.Get("User-Agent");    
       if (!req.Method.Equals("GET"))
       {
          CopyStreams(context.Request.InputStream,req.GetRequestStream());
       }
       return req;
    }
  
    private void forwardResponse(HttpContext context, HttpWebRequest req)
    {
       HttpWebResponse resp =null;
       try
       {
          resp = (HttpWebResponse)req.GetResponse();
       }
       catch(WebException e)
       {
          resp =  (HttpWebResponse)e.Response;
       }
       context.Response.StatusCode = (int)resp.StatusCode;
  
       for (int i = 0; i &lt; resp.Cookies.Count; i++)
       {
           Cookie c = resp.Cookies[i];
           HttpCookie hc = new HttpCookie(c.Name, c.Value);
           hc.Path = c.Path;
           hc.Domain = getServer();
           context.Response.Cookies.Add(hc);
       }
       context.Response.ContentType = resp.ContentType;
       CopyStreams(resp.GetResponseStream(), context.Response.OutputStream);
    }
  
  
    private string makeURL(HttpContext context)
    {
       string strQuery = context.Request.Url.Query;
       string[] arrParams = strQuery.Split('?','&amp;');
       StringBuilder resultingParams = new StringBuilder();
       string strURL=null;
       foreach(string strParam in arrParams )
       { 
          string[] arrNameValue = strParam.Split('=');
          if (!arrNameValue[0].Equals("RedirectURL"))
          {
             if (strParam.Length != 0)
             {
                if (resultingParams.Length != 0)
                   resultingParams.Append("&amp;");
                resultingParams.Append(strParam);
             }
          }
          else if (arrNameValue.Length &gt;1)
             strURL = HttpUtility.UrlDecode(arrNameValue[1]);
       }
  
       if (strURL ==null)
          throw new Exception("Invalid URL format. requestURL parameter is missing");
       String sAppendChar = strURL.Contains("?") ? "&amp;" : "?";
       if (strURL.StartsWith("http:") || strURL.StartsWith("https:"))
       {
           String tmpURL = strURL + sAppendChar + resultingParams.ToString();
           return tmpURL;
       }
       else
       {
           String tmpURL = getServer() + strURL + sAppendChar + resultingParams.ToString();
           return tmpURL;
       }
    }
  
    private void CopyStreams(Stream inStr,Stream outStr)
    {
       byte[] buf = new byte[4096];
       try
       {
          do
          {
             int iRead = inStr.Read(buf,0,4096);
             if (iRead == 0)
                break;
             outStr.Write(buf,0,iRead);
          }
          while (true);
       }
       finally
       {
          outStr.Close();
       }
   }
  }
  </code></pre>