on 10-30-2015 6:28 PM
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!!
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
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
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
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.
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
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!
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!)
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?
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
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.
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.
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.
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
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!
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
101 | |
13 | |
13 | |
11 | |
11 | |
7 | |
6 | |
5 | |
4 | |
4 |
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.