GroupDocs.Assembly for Java supports both file paths and streams for template loading and document saving. Understanding when to use each approach helps you build efficient, scalable applications. File paths are simpler for local file system operations, while streams are essential for memory-based processing, remote templates, and web applications.
The main class involved is:
DocumentAssembler - provides overloads for both file paths and streams
Here are the considerations for choosing between streams and file paths:
Use file paths for simple local file system operations
Use streams for memory-based processing, remote templates, or web applications
Mix file paths and streams as needed for your scenario
Always properly close streams to avoid resource leaks
Note
DocumentAssembler provides two kinds of overloads: one accepts a template path and a result path (String, String), the other accepts a template stream and a result stream (InputStream, OutputStream). Both optionally take LoadSaveOptions. To combine a file path with a stream, open the file as a FileInputStream or FileOutputStream and use the stream overload.
When to Use File Paths
File paths are ideal for:
Simple local file system operations
Templates stored on disk
Output documents saved to disk
Desktop applications with direct file access
importcom.groupdocs.assembly.*;publicstaticvoiduseFilePaths()throwsException{// Simple file path approach
StringtemplatePath="C:\\Templates\\InvoiceTemplate.docx";StringoutputPath="C:\\Output\\Invoice.docx";InvoiceDatadata=newInvoiceData("ABC Corp",1500.00);DocumentAssemblerassembler=newDocumentAssembler();assembler.assembleDocument(templatePath,outputPath,newDataSourceInfo(data,"invoice"));System.out.println("Document assembled using file paths.");}// POJO for the data source (Java has no anonymous types)
publicclassInvoiceData{privatefinalStringcustomerName;privatefinaldoubleamount;publicInvoiceData(StringcustomerName,doubleamount){this.customerName=customerName;this.amount=amount;}publicStringgetCustomerName(){returncustomerName;}publicdoublegetAmount(){returnamount;}}
When to Use Streams
Streams are essential for:
Memory-based processing (no disk I/O)
Templates loaded from databases or remote sources
Web applications serving documents directly
Processing templates in memory for performance
importcom.groupdocs.assembly.*;importjava.io.*;importjava.nio.file.*;importjava.util.Date;publicstaticvoiduseStreams()throwsException{// Load template into memory
byte[]templateBytes=Files.readAllBytes(Paths.get("Template.docx"));try(ByteArrayInputStreamtemplateStream=newByteArrayInputStream(templateBytes);ByteArrayOutputStreamoutputStream=newByteArrayOutputStream()){ReportDatadata=newReportData("Report",newDate());DocumentAssemblerassembler=newDocumentAssembler();assembler.assembleDocument(templateStream,outputStream,newDataSourceInfo(data,"report"));// Use output stream (e.g., send via HTTP, save to database)
byte[]outputBytes=outputStream.toByteArray();Files.write(Paths.get("Output.docx"),outputBytes);System.out.println("Document assembled using streams.");}}// POJO for the data source
publicclassReportData{privatefinalStringtitle;privatefinalDatedate;publicReportData(Stringtitle,Datedate){this.title=title;this.date=date;}publicStringgetTitle(){returntitle;}publicDategetDate(){returndate;}}
Mixed Approach: File Path Input, Stream Output
Load template from file, save to stream. Since assembleDocument accepts either two paths or two streams, open the template file as a FileInputStream:
importcom.groupdocs.assembly.*;importjava.io.*;publicstaticvoidfilePathInputStreamOutput()throwsException{// Template from file path
StringtemplatePath="Template.docx";// Output to memory stream
try(InputStreamtemplateStream=newFileInputStream(templatePath);ByteArrayOutputStreamoutputStream=newByteArrayOutputStream()){ItemDatadata=newItemData("Test",100);DocumentAssemblerassembler=newDocumentAssembler();assembler.assembleDocument(templateStream,outputStream,newDataSourceInfo(data,"item"));// Use output stream (e.g., send via HTTP response)
byte[]outputBytes=outputStream.toByteArray();System.out.println("Document assembled, output size: "+outputBytes.length+" bytes");}}// POJO for the data source
publicclassItemData{privatefinalStringname;privatefinalintvalue;publicItemData(Stringname,intvalue){this.name=name;this.value=value;}publicStringgetName(){returnname;}publicintgetValue(){returnvalue;}}
Mixed Approach: Stream Input, File Path Output
Load template from stream, save to file. Open the result file as a FileOutputStream:
importcom.groupdocs.assembly.*;importjava.io.*;importjava.nio.file.*;importjava.util.Date;publicstaticvoidstreamInputFilePathOutput()throwsException{// Template from memory stream
byte[]templateBytes=Files.readAllBytes(Paths.get("Template.docx"));// Output to file path
StringoutputPath="Output.docx";try(ByteArrayInputStreamtemplateStream=newByteArrayInputStream(templateBytes);OutputStreamoutputStream=newFileOutputStream(outputPath)){ReportDatadata=newReportData("Report",newDate());DocumentAssemblerassembler=newDocumentAssembler();assembler.assembleDocument(templateStream,outputStream,newDataSourceInfo(data,"report"));System.out.println("Document assembled from stream to file.");}}
Web Application Example
In web applications, streams are typically preferred:
Streams enable loading templates from URLs or remote sources:
importcom.groupdocs.assembly.*;importjava.io.*;importjava.net.URL;publicstaticbyte[]loadTemplateFromUrl(Stringurl,Objectdata)throwsException{// Read the template directly from the remote source
try(InputStreamtemplateStream=newURL(url).openStream();ByteArrayOutputStreamoutputStream=newByteArrayOutputStream()){DocumentAssemblerassembler=newDocumentAssembler();assembler.assembleDocument(templateStream,outputStream,newDataSourceInfo(data,"data"));returnoutputStream.toByteArray();}}
Stream Disposal Best Practices
Always properly close streams:
importcom.groupdocs.assembly.*;importjava.io.*;publicstaticvoidproperStreamDisposal()throwsException{// Good: try-with-resources ensures the streams are closed
try(InputStreamtemplateStream=newFileInputStream("Template.docx");OutputStreamoutputStream=newFileOutputStream("Output.docx")){ItemDatadata=newItemData("Test",0);DocumentAssemblerassembler=newDocumentAssembler();assembler.assembleDocument(templateStream,outputStream,newDataSourceInfo(data,"item"));}// Streams are automatically closed here
System.out.println("Streams properly closed.");}
Warning
DocumentAssembler does not close the streams passed to it, neither the template input stream nor the result output stream. Always use try-with-resources statements or close the streams manually to avoid resource leaks.
Performance Considerations
File Paths: Simpler but require disk I/O
Streams: More flexible, can be faster for memory operations
In-Memory Streams (ByteArrayInputStream/ByteArrayOutputStream): Best for small to medium documents
File Streams: Better for large documents to avoid memory pressure
Advanced Usage Topics
To learn more about advanced stream handling, custom stream implementations, and performance optimization, please refer to the advanced usage section.
More resources
GitHub Examples
You may easily run the code above and see the feature in action in our GitHub examples: