cancel
Showing results for 
Search instead for 
Did you mean: 

How to export Crystal Report using BOXI 4 Web Services

Former Member
0 Kudos

Hi Forum,

We have a custom Java web app, from where the user can launch BOXI reports. Behind the scenes, a servlet does the following:

a. connect with BOXI server

b. Pass on the values chosen by the user

c. Retrieve report

d. Display report in PDF format on the browser


Our BOXI setup was upgraded from BOXI 3 to BOXI 4 and since then this functionality does not work.


So far, I have been able to connect to BOXI 4server, get a session and retrieve the report ID. How can I next export this report in a PDF format?

I tried downloading the file and then writing the stream to both a local file object and the servlet's response stream. Both dont work.


The file gets created. But when I try opening the pdf file, I get the error:"Adobe could not open the file because it is either not a supported file type or because the file has been damaged".


Note: I skipped passing the prompts to first get the report to download. Could that be the problem?


I could find no sample code for exporting a report using Web Services. I only see Webi examples, but I need Web Services


Help please? (My code below)


ResponseHolder rh;

String servicesURL = "http://<server>:8080/dswsbobje/services/

Connection oConnection = new Connection(new URL(servicesURL+"session"));


//set credentials

EnterpriseCredential oEnterpriseCredential = EnterpriseCredential.Factory.newInstance();

           

            oEnterpriseCredential.setLogin(userName);  

            oEnterpriseCredential.setPassword(password);           

            oEnterpriseCredential.setAuthType("SecLDAP");

//get session

oSession = new Session(oConnection);

oSession.login(oEnterpriseCredential);

//connect to BIPlatform

oConnection.setURL(new URL(servicesURL+"biplatform"));

BIPlatform oBIPlatform = new BIPlatform(oConnection,oSession.getConnectionState());

GetOptions oGetOptions = GetOptions.Factory.newInstance();

oGetOptions.setIncludeSecurity(FALSE);

//set report Path

String path = "path://InfoObjects/Root Folder/"+properties.getString("REPORT_PATH")+reportName;

//get report to response holder

rh = oBIPlatform.get(path, null);

InfoObjects infoObjects = rh.getInfoObjects();

if (infoObjects == null || infoObjects.getInfoObjectArray().length == 0){

                  System.out.println("Failed to find report: " + reportName);

                  return;

                }

//get report ID

InfoObject reportInfoObject = infoObjects.getInfoObjectArray(0);

String reportCUID = reportInfoObject.getCUID();

int reportID = reportInfoObject.getID();

//IT WORKS UNTIL HERE

//next I tried both writing the report to a file as well as to the response stream. Both are not working!

//set response values

response.setContentType("application/pdf");

response.addHeader("Content-Disposition", "inline;filename=" + reportName +".pdf");

java.io.OutputStream os = response.getOutputStream();

//start downloading report

String downloadID = oBIPlatform.startSingleDownload(reportCUID, 0, null);

//file object

java.io.File newFileObj = new java.io.File(filePath);

if(newFileObj.exists()){

                  newFileObj.delete();

                }

newFileObj.createNewFile();

java.io.FileOutputStream fileOutputStream = new java.io.FileOutputStream(newFileObj);

//download the report

DownloadStatus status = oBIPlatform.downloadFile(downloadID, Long.valueOf("0"));

//write stream to file object and response

fileOutputStream.write(status.getBinaryData());

os.write(status.getBinaryData());

//continue file writing

while(!status.getEndOfFile()){

                 

                  oBIPlatform.downloadFile(downloadID, Long.valueOf(status.getNextReferencePosition()));        

                  System.out.println("Writing.." + status.getBinaryData());

                  fileOutputStream.write(status.getBinaryData()); //write tofile

                  os.write(status.getBinaryData()); //write to response

                }

//close streams

fileOutputStream.close();

os.close();

oBIPlatform.finishDownload(downloadID);

Any help please!!

Accepted Solutions (1)

Accepted Solutions (1)

daniel_paulsen
Active Contributor
0 Kudos

Hi Rose,

from your code, you are actually downloading the RPT binary.  To get a PDF, you can schedule the report to PDF and then download the scheduled instance.

Dan

Former Member
0 Kudos

Dan,

The reports are to be exported on a on-demand basis. The user requests for the reports to be displayed from the custom webapp, from where a servlet connects to BOXI and retrieves the report as a PDF.

Is it possible to export report as a PDF without scheduling it?

daniel_paulsen
Active Contributor
0 Kudos

Hi Rose,

Scheduling to a different format is how it works with the BIPlatform web service, the downside being that you may have to wait a few seconds for the schedule to complete.

You could use the dsws-reportEngine.jar (the reportEngine web service) and view using RetrieveBinaryView to view as PDF.   The ReportEngine web service has been deprecated in BI4 and will not work with Webi reports, but it should work with Crystal Reports as the CR format has not changed in BI4.  The java documentation is here: (http://help.sap.com/businessobject/product_guides/boexir4/en/xi4_wsjava_apiRef_en.zip )

If your reports are "Crystal Reports for Enterprise" reports then there's the Crystal Reports Restful web services which can be used.  This API does not work with reports created in the C++ designer (crw32.exe).

Another alternative is to redirect to OpenDocument which can view the report in PDF format (http://help.sap.com/businessobject/product_guides/boexir4/en/xi4_opendocument_en.pdf ).

Dan

Former Member
0 Kudos

Hi Dan,

You were right. I was downloading the RPT binary and not the instance. I was able to view the downloaded file using Crystal Reports Viewer and it was the template file, not the instance.

I am now trying to schedule the instance.

My report has 3 parameters.And I keep running into null pointer exception, when I try to set the parameter values.

This is what I have so far:

rh = oBIPlatform.get(path, null);

InfoObjects reports = rh.getInfoObjects();

if (reports == null || reports.getInfoObjectArray().length == 0){

                System.out.println("Failed to find report: " + reportName);

                return;

              }

InfoObject reportInfoObject = reports.getInfoObjectArray(0);

String reportCUID = reportInfoObject.getCUID();

int reportID = reportInfoObject.getID();

System.out.println("For template -- ID:  " + reportID + " and CUID: " + reportCUID);

//I GET THE RIGHT REPORT ID AND CUID AT THIS POINT

//get report object

CrystalReport myReport = (CrystalReport)reports.getInfoObjectArray()[0];

SchedulingInfo schedulingInfo = myReport.getSchedulingInfo();

boolean newSchedulingInfo = false;

if (schedulingInfo == null)

            {

             schedulingInfo = SchedulingInfo.Factory.newInstance();

             newSchedulingInfo = true;

               }

boolean schNow = true;

schedulingInfo.setRightNow(schNow);

schedulingInfo.setScheduleType(ScheduleTypeEnum.ONCE);

ReportProcessingInfo reportProcessingInfo = myReport.getPluginProcessingInterface();

ReportParameter[] repParams = reportProcessingInfo.getReportParameters().getParametersArray();

I get a  NULL pointer exception at this point!  My plan was to set the parameter values, set formatting options to PDF and then schedule this instance.

Any help is appreciated!!

Thanks.

daniel_paulsen
Active Contributor
0 Kudos

Hi Rose,

It looks OK.  Are there parameters in the report you've retrieved?

Can you try something like:

ReportParameters repParams = myReport.getPluginProcessingInterface().getReportParameters();

Dan

Former Member
0 Kudos

Hi Dan,

I still get null pointer exception.. but, I made some progress using "OpenDocument".

I created a session, got report ID etc (same code as my previous post). Then I got the logon token from Session Info.

Then I constructed the URL with logon token, report ID, parameter values and set my browser to redirect to that URL.

The only issue is, it asks for BOXI credentials. Once user enters the BOXI credentials, the report gets displayed correctly.

Why does it ask for credentials inspite of me passing the logon token?

//get session

SessionInfo boSI = oSession.login(oEnterpriseCredential);

//get report ID, parameter values etc

//get token

strLogonToken = boSI.getDefaultToken();

//construct openDOcument URL

String redirectURL = "http://<BOXI Server>:8080/BOE/OpenDocument/opendoc/openDocument.jsp?iDocID=Aa3dhagQaEdGqTnh3g.uQn8&sIDType=CUID&token="+strLogonToken+"&lsSowner_division=All&lsSowner_bu=Dave";

response.sendRedirect(redirectURL);

This asks for BOXI credentials and once user enters, it displays the report.

But the end user is not supposed to have BOXI credentials!!

Once I have the URL constructed, am I supposed to download the report from the URL and then stream it to the browser?

Help!! The DEV guide does not say anything about accessing the report, after the URL is constructed!

DellSC
Active Contributor
0 Kudos

You might try URL Encoding the login token and see if that helps.

-Dell

Former Member
0 Kudos

URL encoding did not work. I tried encoding both the token & the URL..

//get token

SessionInfo boSI = oSession.login(oEnterpriseCredential);

strLogonToken = boSI.getDefaultToken();

//decode token

URLDecoder.decode(strLogonToken,"UTF-8");

//form URL

String redirectURL = "http://<BOXI Server>:8080/BOE/OpenDocument/opendoc/openDocument.jsp?iDocID=Aa3dhagQaEdGqTnh3g.uQn8&sIDType=CUID&token="+strLogonToken+"&lsSowner=All&sOutputFormat=P";

//decode URL

URLDecoder.decode(redirectURL,"UTF-8");

//send to browser

response.sendRedirect(redirectURL);

It still prompts user to login to BOXI..

BTW, The logon token prints as:

10.215.11.98:6400@5269610JbBjuLrMOHVb2Rt40GqYxMa5269609JuuA2JvBFpe38uj8fOwmYXK

Should I parse out the IP? and only pass "5269610JbBjuLrMOHVb2Rt40GqYxMa5269609JuuA2JvBFpe38uj8fOwmYXK" as the token? (Wild thought!)

DellSC
Active Contributor
0 Kudos

Don't decode the URL before doing the redirect. - you want to redirect using the encoded token.

-Dell

Former Member
0 Kudos

Encoding only the token did not work, either.

oSession = new Session(oConnection);

SessionInfo boSI = oSession.login(oEnterpriseCredential);

strLogonToken = boSI.getDefaultToken();

String redirectURL = "http://<BOXI_Server>:8080/BOE/OpenDocument/opendoc/openDocument.jsp?iDocID=Aa3dhagQaEdGqTnh3g.uQn8&sIDType=CUID&token="+URLEncoder.encode(strLogonToken)+"&lsSowner=All&sOutputFormat=P";

response.sendRedirect(redirectURL);

Should I get the token a different way?

DellSC
Active Contributor
0 Kudos

I know it sounds crazy, but I've frequently had better luck putting the token on the end of the URL instead of in the middle.

You could try that.  In the meantime, I'm doing a bit of research to see what else is possible.

-Dell

P.S.

Would you please post what the token looks like after you get it?  You can "scrub" it to replace the server info and anything else that's sensitive info.  I just want to see whether it looks like what I expect it to.  Thanks!

Message was edited by: Dell Stinnett-Christy

daniel_paulsen
Active Contributor
0 Kudos

Hi Rose,

One possibility is that the encoded token is exceeding the URL limits of IE causing some of it to get cut off.  If you try a different browser (ie Chrome) do you see the same problem or does it work?

If the length of the token is causing problems with openDocument, then you can pass the token using a POST rather than a GET.

The following Knowledge base article explains it: 1842106

this is typically a problem with a serialized session token, and not the defaultToken.

Former Member
0 Kudos

Dell: Moving token to end of string did not work.

Dan: I get the same issue with 3 different browsers. I even tried reducing the URL length by choosing parameter values that have a short value. But the issue persists.

I will check the knowledge base. Thank you.

And might re-investigate scheduling the report on BI Platform,  like I'd originally started. Again, retrieiving parameter list was causing null pointer exception there.

Former Member
0 Kudos

I finally got this to work!

The issue was that a logon token retrieved using web service URL oSession.login(oEnterpriseCredential)  does not work. I needed a token retrieved from a CMS session: mySessionMgr.logon(boUserId, boPassword, currentServer, authType);

Here is the code:

Original code (that did not work)

Web Service URL: http://server1:8080/dswsbobje/services/

//get connection

servicesURL = http://<server1>:8080/dswsbobje/services/

Connection oConnection = new Connection(new URL(servicesURL+"session"));

EnterpriseCredential oEnterpriseCredential = EnterpriseCredential.Factory.newInstance();

oEnterpriseCredential.setLogin(userName);  

oEnterpriseCredential.setPassword(password);           

oEnterpriseCredential.setAuthType("SecLDAP");

//get session

SessionInfo boSI = oSession.login(oEnterpriseCredential);

strLogonToken = boSI.getDefaultToken();

//construct URL

String redirectURL = "http://server1:8080/BOE/OpenDocument/opendoc/openDocument.jsp?iDocID="+repID+"&sIDType=CUID&token="+URLEncoder.encode(strLogonToken)+"&lsSowner=Dave&lsSowner_div=HR&sOutputFormat=P";

response.sendRedirect(redirectURL);

In this case, it always prompted user to login to BOXI, irrespective of me sending the token.

Then I changed it as follows:

//CMS URL

String cmsUrl = "server2:6400";

ISessionMgr mySessionMgr = CrystalEnterprise.getSessionMgr();

IEnterpriseSession eSession = null;

String[] boxiServers = cmsUrl.split(",");

Random randomGenerator = new Random();

int randomPosition = randomGenerator.nextInt(boxiServers.length);

String currentServer = boxiServers[randomPosition].trim();

//get session

eSession = mySessionMgr.logon(boUserId, boPassword, currentServer, authType);

//get token

cmsToken = eSession.getLogonTokenMgr().createLogonToken("", 120, 100);

//URL with CMS token, pointing to web service URL

String redirectURL = "http://server1:8080/BOE/OpenDocument/opendoc/openDocument.jsp?iDocID="+repID+"&sIDType=CUID&token="+URLEncoder.encode(cmsToken)+"&lsSowner=Dave&lsSowner_div=HR&sOutputFormat=P";

response.sendRedirect(redirectURL);

This worked like a charm!

Thank you Dell & Daniel for your help.

Answers (1)

Answers (1)

Former Member
0 Kudos

Per the Developer Guide, Report Engine is deprecated in BOXI 4.

But I see it listed under List Services:

http://<myservername>:8080/dswsbobje/services/ReportEngine

Available Operations

  • getDataSourceObjectLOV
  • getDocumentInformation
  • getImage

And also in Java Docs:

com.businessobjects.dsws.reportengine

Class ReportEngine

"ReportEngine class is a proxy that can consume the ReportEngine Web Service and that is mapped on its WSDL.  ReportEngine provides services to return DocumentInformation and Image objects."

However, I am unable to import "com.businessobjects.dsws.reportengine" in my Java code, in spite of having all BOXI 4 JArs.

So is Report Engine available for use or not? Argh!