Jasper Plugin PDF File Sometimes Not Returned

Questions and answers on developing, deploying and using plugins and JavaBeans

Jasper Plugin PDF File Sometimes Not Returned

Postby tkilshaw1553613063 » Tue Jul 02, 2024 9:00 pm

We are using Servoy Version: 2023.3.6.3848_LTS, developing on Windows and deploying to Linux.

All of our reports are returned to the user as PDFs. Sometimes, although the plugin appears to be creating the required document it is not returned to the user. This problem happens if the user has left the Servoy solution running without interaction for two hours or more and then clicks a Print button.

We are using this method of the plugin:
Code: Select all
@param {Object} reportDataSource the server name or foundset to run the report on
@param {String} report the report file (relative to the reports directory)
@param {Object} outputOptions the output file (must specify an absolute path) or null if not needed
@param {String} outputType the output format; use the constants node for available output formats
@param {Object} parameters a parameter map to be used when running the report
@return {byte[]} the generated reported as a byte array
byte[] runReport(reportDataSource:Object, report:String, outputOptions:Object, outputType:String, parameters:Object)


Our call from Servoy is:

Code: Select all
plugins.jasperPluginRMI.runReport( goFieldsDS, sJasperTemplate, null, plugins.jasperPluginRMI.OUTPUT_FORMAT.PDF, oParams );


Note that we don't send anything for the third argument: outputOptions.

Debugging has shown that the code spends the same amount of time in the Jasper plugin whether or not a PDF file is returned, which implies that the PDF is being created but we do not know where.

Looking through the source code for the JasperPluginRMI I see:

Code: Select all
// in JasperReportsWebViewer.show 61

    if(application instanceof IWebClientPluginAccess)
    {
      IWebClientPluginAccess wapp = (IWebClientPluginAccess) application;
      IPageContributor pc = wapp.getPageContributor();
      if (pc != null) {
        String url = wapp.serveResource(getFixedFileName(file, ext), jsp, mimeType);
        wapp.showURL(url, "_self", null, 0);
      }
    }

At this point the value of "file" is still null.

The getFixedFileName(file, ext) call looks like this:
Code: Select all
    if (file == null || file.length() == 0)
    {
      Calendar cal = Calendar.getInstance(TimeZone.getDefault());
      String DATE_FORMAT = "yyyyMMddHHmmss";
      java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat(DATE_FORMAT);
      sdf.setTimeZone(TimeZone.getDefault());
      fixedFileName = "report_" + sdf.format(cal.getTime()) + "." + ext;
    }

So that creates a file name with no path. For example: report_20240702083040.pdf

The key to understanding what happens in:
Code: Select all
        String url = wapp.serveResource(getFixedFileName(file, ext), jsp, mimeType);
        wapp.showURL(url, "_self", null, 0);

depends on:
Code: Select all
      IWebClientPluginAccess wapp = (IWebClientPluginAccess) application;


The most recent Javadocs I can find are in https://developer.servoy.com/docs/publi ... index.html

There it says:

Code: Select all
Methods inherited from interface com.servoy.j2db.plugins.IAllWebClientPluginAccess
serveResource, serveResource, showURL, showURL, showURL


And those are precisely the methods whose details I need to see.

But unlike the other interfaces inherited by IWebClientPluginAccess there is no information given there on IAllWebClientPluginAccess!

So, I am unable to figure out just what this does:

Code: Select all
        String url = wapp.serveResource(getFixedFileName(file, ext), jsp, mimeType);
        wapp.showURL(url, "_self", null, 0);


What actually happens when wapp.serveResource(getFixedFileName(file, ext), jsp, mimeType) is called?

Is the PDF file being created and written to a folder on the server?

If so, where?

If not, is it being created in-memory?

Any help would be greatly appreciated.
tkilshaw1553613063
 
Posts: 52
Joined: Tue Mar 26, 2019 5:11 pm

Re: Jasper Plugin PDF File Sometimes Not Returned

Postby sbutler » Tue Jul 02, 2024 11:46 pm

You might consider adjusting your code so you can have more control over what's happening. For example...

Get the bytes and stream it to the user's browser
Code: Select all
var reportBytes = plugins.jasperPluginRMI.runReport( goFieldsDS, sJasperTemplate, null, plugins.jasperPluginRMI.OUTPUT_FORMAT.PDF, oParams );
plugins.file.writeFile("report.pdf", reportBytes, "application/pdf");


Get the bytes, save a copy on the server and stream it to the user's browser
Code: Select all
var reportBytes = plugins.jasperPluginRMI.runReport( goFieldsDS, sJasperTemplate, null, plugins.jasperPluginRMI.OUTPUT_FORMAT.PDF, oParams );
plugins.file.writeFile(plugins.file.convertToJSFile("c:/archive/report.pdf"), reportBytes, "application/pdf"); //server copy
plugins.file.writeFile("report.pdf", reportBytes, "application/pdf");


Save it to disk and stream it to the user's browser or open it in PDF viewer
Code: Select all
var fileName = "report.pdf";
var reportFile = plugins.file.getDefaultUploadLocation() + "/" + fileName;
plugins.jasperPluginRMI.runReport( goFieldsDS, sJasperTemplate, reportFile, plugins.jasperPluginRMI.OUTPUT_FORMAT.PDF, oParams );
var remoteFile = plugins.file.convertToRemoteJSFile("/" + fileName);
var fileURL = plugins.file.getUrlForRemoteFile(remoteFile);
application.showUrl(fileURL, "_blank"); //or pass the url into Servoy's PDF Viewer
Scott Butler
iTech Professionals, Inc.
SAN Partner

Servoy Consulting & Development
Servoy University- Training Videos
Servoy Components- Plugins, Beans, and Web Components
Servoy Guy- Tips & Resources
ServoyForge- Open Source Components
User avatar
sbutler
Servoy Expert
 
Posts: 765
Joined: Sun Jan 08, 2006 7:15 am
Location: Cincinnati, OH

Re: Jasper Plugin PDF File Sometimes Not Returned

Postby tkilshaw1553613063 » Wed Jul 03, 2024 5:37 pm

Greatly appreciated Scott. I'll give that a try.

Terry
tkilshaw1553613063
 
Posts: 52
Joined: Tue Mar 26, 2019 5:11 pm

Re: Jasper Plugin PDF File Sometimes Not Returned

Postby tkilshaw1553613063 » Wed Jul 03, 2024 8:03 pm

Unfortunately convertToRemoteJSFile() requires a file path that starts with "/". But I am developing on Windows so the file path starts with "C:\" and that fails.

So I don't see how your call to:

plugins.file.convertToJSFile("c:/archive/report.pdf")

works.

Any suggestions?

thanks.
tkilshaw1553613063
 
Posts: 52
Joined: Tue Mar 26, 2019 5:11 pm

Re: Jasper Plugin PDF File Sometimes Not Returned

Postby mboegem » Thu Jul 04, 2024 7:53 am

Hi Terry,

What type of Servoy-client do you use, and where do you expect the pdf file to be written to?
Marc Boegem
Solutiative / JBS Group, Partner
Servoy Specialist
• Servoy Certified Developer
• Servoy Valued Professional
• Freelance Developer

Image
User avatar
mboegem
 
Posts: 1765
Joined: Sun Oct 14, 2007 1:34 pm
Location: Amsterdam

Re: Jasper Plugin PDF File Sometimes Not Returned

Postby tkilshaw1553613063 » Thu Jul 04, 2024 6:42 pm

I have made this work but wonder if this is right.

I now write the PDF file to the DefaultUploadLocation and then I take the bytes of the report and set them into a RemoteFile, which seems redundant to me. But I can't make this work if I still pass null for the third plugins.jasperPluginRMI.runReport() argument.

I have no idea what a RemoteFile is. Is this a file on the file system? Is it some kind of in-memory file?

And when I call plugins.file.convertToRemoteJSFile( "/" + sReportFilename ) that uses only the file's name not its path so it is not clear to me what is happening here and therefor what may need to be cleaned up later. Certainly I need at some point to delete the PDF files from the DefaultUploadLocation but do I also need to delete the RemoteFile? If so from where?

Code: Select all
  var sReportFilename = makeReportFilename( );
  var sReportFilepath = plugins.file.getDefaultUploadLocation( ) + java.io.File.separator + sReportFilename;

  var oBytes = plugins.jasperPluginRMI.runReport( goFieldsDS, sJasperTemplate, sReportFilepath, plugins.jasperPluginRMI.OUTPUT_FORMAT.PDF, oParams );

  var oRemoteFile = plugins.file.convertToRemoteJSFile( "/" + sReportFilename );
  oRemoteFile.setBytes( oBytes, true );
  var sFileURL = plugins.file.getUrlForRemoteFile( oRemoteFile );
  application.showURL( sFileURL, "_blank" );


thanks,

Terry
tkilshaw1553613063
 
Posts: 52
Joined: Tue Mar 26, 2019 5:11 pm

Re: Jasper Plugin PDF File Sometimes Not Returned

Postby tkilshaw1553613063 » Thu Jul 04, 2024 6:56 pm

In response to Marc Boegem's questions:

We are running Servoy Version: 2023.3.6.3848_LTS in the NG mode but not in Titanium yet. We develop on Windows and deploy to Linux.

Originally we used:

plugins.jasperPluginRMI.runReport( goFieldsDS, sJasperTemplate, null, plugins.jasperPluginRMI.OUTPUT_FORMAT.PDF, oParams );

This depends on Servoy to create a report name then return the PDF to the user. But when a Servoy form with a Print button on it is left for more than two hours, when the user clicks the Print button Servoy acts as if it is creating the PDF but then returns nothing to the user. This does not stop Servoy from working. We have no idea where or even if Servoy is writing that file.

Following suggestions from Scott Butler we are now creating our own report filename. Servoy's name included year, day, hour, minute and seconds. We have added milliseconds. We then construct a file path to Sevoy's DefaultUploadLocation and pass that with the appended filename.

We will deploy that to our Linux server soon to see if it fixes the problem.

thanks,

Terry
tkilshaw1553613063
 
Posts: 52
Joined: Tue Mar 26, 2019 5:11 pm

Re: Jasper Plugin PDF File Sometimes Not Returned

Postby mboegem » Fri Jul 05, 2024 11:29 am

Hi Terry,

I haven't heard reports from users not able to generate their reports.
Anyway, the function below is pretty simple and shows 3 ways of handling the byteArray:
1) Download it to the users download folder
2) Store it on the server in the default upload folder in a subfolder called 'UserReports'
3) Preview it in the PDFjs component within your application. (using modal dialog)

Code: Select all
var _aBytes = plugins.jasperPluginRMI.runReport( goFieldsDS, sJasperTemplate, null, plugins.jasperPluginRMI.OUTPUT_FORMAT.PDF, oParams );
   var _sFileName = 'myReportName.pdf'
   
   // download
   plugins.file.writeFile(_sFileName, _aBytes);
   
   // store on server
   var _sPath = plugins.file.getDefaultUploadLocation() + '/UserReports/' + _sFileName;
   plugins.file.writeFile(plugins.file.convertToJSFile(_sPath), _aBytes);
   
   // preview in PDFjs
   forms.preview_pdf.showFID(_aBytes);


The previewer is nice because from there, users are able to print directly, or use the download button.

The preview form should be easy:
1) create a form with the PDFjs component
2) create a form variable '$aBytes' and use that as the dataprovider on the component.
3) create a function showFID(_aBytes), that will set the incoming byteArray into the form variable and open the form as modal dialog.

Hope this helps in order to choose the best way of handling your report.
Marc Boegem
Solutiative / JBS Group, Partner
Servoy Specialist
• Servoy Certified Developer
• Servoy Valued Professional
• Freelance Developer

Image
User avatar
mboegem
 
Posts: 1765
Joined: Sun Oct 14, 2007 1:34 pm
Location: Amsterdam


Return to Plugins and Beans

Who is online

Users browsing this forum: No registered users and 7 guests

cron