PDF convert doesn't work in multi-thread Java application

Hi,

I tried to convert PDF to PDF/A by using Aspose library, it works on single thread application, however when I tried to run it in multi-thread application by using ExecutorService, got the EmptyValueException: CreationDate value is empty when save the Document after converting.

Multi-threading code is :slight_smile:

ExecutorService executor = Executors.newFixedThreadPool(5);
for (int i = 0; i < 2; i++) {
Runnable worker = new WorkerThread(“0” + i);
executor.execute(worker);
}
Convert code is :
pdfStream = new ByteArrayInputStream(pdf);
Document pdfDocument = new Document(pdfStream);
pdfOutStream = new ByteArrayOutputStream();
boolean success = pdfDocument.convert(“D:/NotBackedUp/projects/glenspdf/tmp/file.log”, PdfFormat.PDF_A_1A, ConvertErrorAction.Delete);
if (!success) {
throw new RuntimeException (“Could not convert the PDF to a PDF/A-1A format PDF.”);
}
//DocumentInfo di = pdfDocument.getInfo();
//System.out.println(“CreationDate is:” + di.getCreationDate());
pdfDocument.save(pdfOutStream);
Exception is lie:
Exception in thread “pool-1-thread-2” class com.aspose.pdf.exceptions.EmptyValueException: CreationDate value is empty
com.aspose.pdf.internal.p17.z14.m10(Unknown Source)
com.aspose.pdf.internal.p106.z1.m1(Unknown Source)
com.aspose.pdf.internal.p106.z5.m1(Unknown Source)
com.aspose.pdf.internal.p102.z18.m1(Unknown Source)
com.aspose.pdf.internal.p102.z16.m1(Unknown Source)
com.aspose.pdf.internal.p17.z13.m1(Unknown Source)
com.aspose.pdf.ADocument.saveInternal(Unknown Source)
com.aspose.pdf.Document.saveInternal(Unknown Source)
com.aspose.pdf.ADocument$3.m1(Unknown Source)
com.aspose.pdf.internal.p789.z2.m2(Unknown Source)
com.aspose.pdf.internal.p789.z3.m1(Unknown Source)
com.aspose.pdf.ADocument.save(Unknown Source)
com.aspose.pdf.Document.save(Unknown Source)
nz.govt.mymsd.utils.AsposePDFConverter.convertPDFToPDFA(AsposePDFConverter.java:145)
ConvertTest.runTest(ConvertTest.java:90)
WorkerThread.processCommand(MultiThreadConvertTest.java:64)
WorkerThread.run(MultiThreadConvertTest.java:50)
java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
java.lang.Thread.run(Unknown Source)
at com.aspose.pdf.internal.p17.z14.m10(Unknown Source)
at com.aspose.pdf.internal.p106.z1.m1(Unknown Source)

Actually I can see there is a CreationDate value in the DocumentInfo, not sure why Aspose complain about it.

Wondering if Aspose PDF converting works in the Java multi-thread environment? Have anyone got the same issue before?

Thanks

Hi Ryan,


Thanks for your inquriy. I am looking into the issue and will update you soon.

Best Regards,

Hi Ryan,

Thanks for your inquiry. I have tested your scenario with a sample PDF document using Aspose.Pdf for Java 11.8.0 and unable to notice any issue. I will appreciate it if you please share your complete sample code along with source PDF document, so we will investigate it further and will provide you information accordingly.

public static void main(String[] args) throws Throwable {
    ThreadExecutor asposeExecutor = new ThreadExecutor();
    asposeExecutor.execute();
}

public static class ThreadExecutor {
    public void execute() throws IOException {
        ExecutorService executor = Executors.newFixedThreadPool(5);
        for (int i = 0; i < 2; i++) {
            Runnable worker = new AsposeThread("0" + i);
            executor.execute(worker);
        }
        executor.shutdown();
    }
}

public static class AsposeThread implements Runnable {
    private String threadno;

    public AsposeThread(String thread_no) {
        this.threadno = thread_no;
    }

    @Override
    public void run() {
        try {
            System.out.println("Processing: " + threadno);
            Document pdfDocument = new Document(new ByteArrayInputStream(FileUtils.readFileToByteArray(new File("D:/Downloads/Input.pdf"))));

            // pdfOutStream = new ByteArrayOutputStream();
            boolean success = pdfDocument.convert("E:/data/file.log", PdfFormat.PDF_A_1A, ConvertErrorAction.Delete);

            if (!success) {
                throw new RuntimeException("Could not convert the PDF to a PDF/A-1A format PDF.");
            }

            pdfDocument.save(myDir + threadno + "_input_pdfaout.pdf");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

We are sorry for the inconvenience.

Best Regards,

Thanks for the reply Tilal!

My application is slightly different and I was using ExecutorService.

However when I tried you application. If I change the PDF file to the file I was using, which is a 5 pages sample PDF. Then add a loop in the run() method to make it running longer, then I can get the same EmptyValueException: CreationDate value is empty error.

@Override

public void run() {
for (int i = 0; i < 20; i ++) {

try {

System.out.println("Processing: "+threadno);



Document pdfDocument = new Document(new ByteArrayInputStream(FileUtils.readFileToByteArray(new File(PDF_PATH + “5pagesSample.pdf”))));



//pdfOutStream = new ByteArrayOutputStream();



boolean success = pdfDocument.convert(PDF_PATH + “tmp/file.log”, PdfFormat.PDF_A_1A, ConvertErrorAction.Delete);

if (!success) {

throw new RuntimeException (“Could not convert the PDF to a PDF/A-1A format PDF.”);

}

pdfDocument.save(PDF_PATH+threadno+ “_input_pdfaout.pdf”);

} catch (Exception e) {

e.printStackTrace();

}
}
}

I tried to run it 10 times then get the error, you can try a few more times if don’t get the error.

Thanks

Ryan

Hi Ryan,


Thanks for your inquiry. I am looking into it and will update you shortly.

Best Regards,
Hi Ryan,

ryanxs:
Thanks for the reply Tilal!

My application is slightly different and I was using ExecutorService.


Thanks for your patience. Yes, a slight difference but I also using ExecutorService.

ryanxs:


However when I tried you application. If I change the PDF file to the file I was using, which is a 5 pages sample PDF. Then add a loop in the run() method to make it running longer, then I can get the same EmptyValueException: CreationDate value is empty error.

@Override

public void run() {
for (int i = 0; i < 20; i ++) {

try {

System.out.println("Processing: "+threadno);



Document pdfDocument = new Document(new ByteArrayInputStream(FileUtils.readFileToByteArray(new File(PDF_PATH + "5pagesSample.pdf"))));



//pdfOutStream = new ByteArrayOutputStream();



boolean success = pdfDocument.convert(PDF_PATH + "tmp/file.log", PdfFormat.PDF_A_1A, ConvertErrorAction.Delete);

if (!success) {

throw new RuntimeException ("Could not convert the PDF to a PDF/A-1A format PDF.");

}

pdfDocument.save(PDF_PATH+threadno+ "_input_pdfaout.pdf");

} catch (Exception e) {

e.printStackTrace();

}
}
}

I tried to run it 10 times then get the error, you can try a few more times if don't get the error.

Thanks

Ryan

I have tried the code in 20 iterations both in run method and main method but I am afraid I am still unable to notice reported exception. I am using Aspose.Pdf for Java 11.9.0, JDK 1.7 and Windows 7 64 bit. I will appreciate it if you please share your source PDF document and environment details here as well, we will further investigate the issue and will provide you information accordingly.

We are truly sorry for the inconvenience.

Best Regards,

Hi Tilal,


I’ve attached the PDF I used. I’m using 32bit Windows Java 1.7 now. I’ve got the same error with 64bit Windows Java1.8 too.

The aspose-pdf is 11.8.0. I’ll try 11.9.0 later.

I just tired the Aspose 11.9.0. The chance to get the exception is smaller but I still can see it. If you don’t the error by using 2 threads, probably can try increasing the threads number to 5.



The full application I’m using is:

package aspose;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.apache.commons.io.FileUtils;

import com.aspose.pdf.ConvertErrorAction;
import com.aspose.pdf.Document;
import com.aspose.pdf.License;
import com.aspose.pdf.PdfFormat;

public class TestThreadExecutor {

static String PDF_PATH = “D:/NotBackedUp/tmp/glenspdf/”;
public static void main(String[] args) throws Throwable {



initLicense();

ThreadExecutor asposeExecutor = new ThreadExecutor();

asposeExecutor.execute();

}
public static class AsposeThread implements Runnable {


private String threadno;


public AsposeThread(String thread_no) {

this.threadno = thread_no;

}



@Override

public void run() {
for (int i = 0; i < 20; i ++) {

try {

System.out.println(“Processing: “+threadno);


Document pdfDocument = new Document(new ByteArrayInputStream(FileUtils.readFileToByteArray(new File(PDF_PATH + “5pagesSample.pdf”))));

//Document pdfDocument = new Document(new ByteArrayInputStream(FileUtils.readFileToByteArray(new File(PDF_PATH + “bp_super.pdf”))));

//pdfOutStream = new ByteArrayOutputStream();


boolean success = pdfDocument.convert(PDF_PATH + “tmp/file.log”, PdfFormat.PDF_A_1A, ConvertErrorAction.Delete);

if (!success) {

throw new RuntimeException (“Could not convert the PDF to a PDF/A-1A format PDF.”);

}

pdfDocument.save(PDF_PATH+threadno+ “_input_pdfaout.pdf”);

} catch (Exception e) {

e.printStackTrace();

}
}
}

}

public static class ThreadExecutor {


public void execute() throws IOException {


ExecutorService executor = Executors.newFixedThreadPool(5);

for (int i = 0; i < 5; i++) {

Runnable worker = new AsposeThread(“0”+i);

executor.execute(worker);

}

executor.shutdown();

}

}
public static void initLicense() {
License license = new License();
try {
File initialFile = new File(PDF_PATH + “Aspose.Total.Java.lic”);
InputStream is = new FileInputStream(initialFile);
//InputStream is = getClass().getResourceAsStream(”/aspose/Aspose.Total.Java.lic”);
license.setLicense(is);
} catch (Exception e) {
System.out.println(“Aspose License is not set correctly!”);
e.printStackTrace();
}
if (license.toString() != null) {
System.out.println(“Aspose License is set!”);
}
}

}


Hi Ryan,


Thanks for sharing your source document. I have tested the scenario using your shared PDF document and able to notice the reported exception, so I have logged a ticket PDFJAVA-36185 in our issue tracking system for further investigation and rectification. We will notify you as soon as it is resolved.

We are sorry for the inconvenience.

Best Regards,

Hi Aspose,

Has there been any progress investigating this multi-threading issue?

See internal issue ticket: PDFJAVA-36185

We will be relying on multi-threading as we start to scale our use of the library up. So will be critical to our implementation.

Regards,
Glenn (Ryan’s co-worker)

Hi Ryan,


Thanks for contacting support.

The above stated issue PDFJAVA-36185 is related to multi-threading and its pending for review. However as soon as we have some definite updates regarding its resolution, we will let you know.

The issues you have found earlier (filed as PDFJAVA-36185) have been fixed in Aspose.Pdf for Java 16.11.0.


This message was posted using Notification2Forum from Downloads module by Aspose Notifier.
(4)

Thanks for the fix!
As I tested the new version, the previous exception seems disappeared. However sometimes I get a new error when I use more than 3 threads(for example 10 threads):

Caused by: java.io.FileNotFoundException: .\file.log (Access is denied)

which happens at:

boolean success = pdfDocument.convert("./file.log", PdfFormat.PDF_A_1A, ConvertErrorAction.Delete);

Do you have any suggestion how to set the log files in the com.aspose.pdf.Document.convert
method for multithreading?


Hi Ryan,


Thanks for your feedback. I have tested the scenario and unable to notice the reported exception with log file, it is being overwritten at my end with above code. However you may try to add some counter in file name e.g threadno as following. Hopefully, it will help you to resolve the issue.

boolean success =
pdfDocument.convert(
“E:/data/”+threadno+“file.log”,
PdfFormat.
PDF_A_1A, ConvertErrorAction.Delete);


Best Regards,

Hi Ryan,


Thanks for sharing the details.

Adding more to Tilal’s comments, you may consider using Stream object to save conversion log.

Thanks for the reply!

I tried you way to use different log file name for different thread and it works.

However as we continue create/delete thread, it’ll create a lot of log files in the folder. Wondering if there is a way to not write the log file when do the PDF converting?


Hi Ryan,


Thanks for your feedback. It is good to know that suggestion worked for you. However as stated above file overwriting option should work, might be you have some rights issue on specific machine.

Furthermore, if you do not want to save log files then you may use stream parameter as following, it will help you to accomplish the task.

document.convert(new ByteArrayOutputStream(), com.aspose.pdf.PdfFormat.PDF_A_1B, com.aspose.pdf.ConvertErrorAction.Delete);

Best Regards,

Thanks for the help!

Stream parameter is what we need.


Hi Ryan,


Thanks for your feedback. It is good to know that you have managed to accomplish your requirements.

Please keep using Aspose.Pdf and feel free to contact us for any further assistance.

Best Regards,