Manage documents with code examples using Java APIs
Code examples that illustrate how the Bonita Engine Java APIs let you create, add a new version and attach documents to a Bonita process.
More information
You might want to consult the document documentation first.
A document is treated in a similar way to a variable in Bonita Engine database. It is defined in Bonita Studio or programmatically, and is stored in the Bonita Engine database. Inside a process instance, a document is a byte stream.
Set or update the value of a document in a process operation using a script
In a process operation, you might want to set / update the value of a document data using a groovy script instead of simply use a contract input.
The script should return a DocumentValue .
N.B: All the following examples deal with single document data. For multiple document data, just adapt the scripts to return a list of DocumentInput instead of a document input.
Create a new document
The following groovy scripts create a new document from an existing contract input / url / file.
import java.nio.file.Files
import org.bonitasoft.engine.bpm.contract.FileInputValue
import org.bonitasoft.engine.bpm.document.DocumentValue
// From a contractInput
def DocumentValue createNewDocument(FileInputValue fileFromContract) {
new DocumentValue(fileFromContract.content, fileFromContract.contentType, fileFromContract.fileName)
}
// From an url
def DocumentValue createNewDocument(String url) {
new DocumentValue(url)
}
// From an existing file on the fileSystem
def DocumentValue createNewDocument(File file) throws IOException {
def mimeType = Files.probeContentType(file.toPath())
new DocumentValue(file.bytes, mimeType, file.name)
}
Update the value of an existing document if a new content is provided
This following script is a way to address the use case of an optional update of the value of a document:
A user might want to change the value of a document, or not. If a new document is uploaded then the value of the data must be updated, if not then the data should be left unchanged.
import java.nio.file.Files
import org.bonitasoft.engine.bpm.contract.FileInputValue
import org.bonitasoft.engine.bpm.document.DocumentValue
// From a contractInput
def DocumentValue optionalUpdateDocument(long documentId, FileInputValue fileFromContract) {
return fileFromContract
? new DocumentValue(documentId, fileFromContract.content, fileFromContract.contentType, fileFromContract.fileName)
: new DocumentValue(documentId)
}
// From an url
def DocumentValue optionalUpdateDocument(long documentId, String url) {
return url
? new DocumentValue(documentId, url)
: new DocumentValue(documentId)
}
// From an existing file on the fileSystem
def DocumentValue optionalUpdateDocument(long documentId, File file) throws IOException {
return file
? new DocumentValue(documentId, file.bytes, Files.probeContentType(file.toPath()), file.name)
: new DocumentValue(documentId)
}
Create a case with documents
The following method, createCaseWithDocument
, creates a case and attaches documents to it.
import java.nio.file.Files
import org.bonitasoft.engine.bpm.document.DocumentValue
import org.bonitasoft.engine.exception.BonitaException
import org.bonitasoft.engine.expression.ExpressionBuilder
import org.bonitasoft.engine.operation.OperationBuilder
import com.bonitasoft.engine.api.ProcessAPI
/**
* In this example, `documents` is a map which link a document data (key) to a file (value)
* This map will be converted to operations to set document data with DocumentValue
* We assume in this example that all documents are initialized with Files (i.e contents), it could be URLs!
*/
def createCaseWithDocument(String processDefinitionName,
String processVersion,
Map<String, File> documents,
ProcessAPI processAPI) throws BonitaException {
def processDefinitionId = processAPI.getProcessDefinitionId(processDefinitionName, processVersion)
def operations = []
def listExpressionsContext = [:]
// ----- create setDocument operations -----
documents.keySet().each { documentName ->
def file = documents.get(documentName)
def mimeType = Files.probeContentType(file.toPath())
def documentValue = new DocumentValue(file.bytes, mimeType, file.name)
def expressionName = documentName + "Reference"
def expression = new ExpressionBuilder().createInputExpression(expressionName, DocumentValue.class.getName())
def operation = new OperationBuilder().createSetDocument(documentName, expression)
operations.add(operation)
listExpressionsContext.put(expressionName, documentValue)
}
// ----- start process instance -----
processAPI.startProcess(processDefinitionId, operations, listExpressionsContext)
}
Attach a document to a case
To attach a first version of a document data to a case, use the attachDocument
method of the process API.
To attach a new version of a document data to a case, use the attachDocumentNewDocumentVersion
method of the process API.
import java.nio.file.Files
import com.bonitasoft.engine.api.ProcessAPI
// Set the first value of the document `documentName` with the file `document`
// throw an exception if `documentName` has already a value
def attachDocumentToCase(ProcessAPI processAPI, long processInstanceId, String documentName, File document) {
def mimeType = Files.probeContentType(document.toPath())
processAPI.attachDocument(processInstanceId, documentName, document.name, mimeType, document.bytes)
}
// Update the value of the document `documentName` with the file `document`
// throw an exception if `documentName` doesn't already have a value
def attachNewDocumentVersionToCase(ProcessAPI processAPI, long processInstanceId, String documentName, File document) {
def mimeType = Files.probeContentType(document.toPath())
processAPI.attachNewDocumentVersion(processInstanceId, documentName, document.name, mimeType, document.bytes)
}
Delete content of archived case documents based on archive date
The use case is to free database disk space by deleting the content of archived case documents older than a certain date. However, it keeps metadata attached to the process instance.
searchArchivedDocumentsOlderThanArchivedDate
look for archived documents.
deleteArchivedDocumentsOlderThan
delete the content of the document.
Although the document binary will be deleted, records will remain in the database. To completely remove the document from the database, delete the process instance to which it is attached, this will delete all elements of the process instance on cascade. |
//Search for documents of archived cases with archived date older than "archivedDate"
def SearchResult searchArchivedDocumentsOlderThanArchivedDate(ProcessAPI processAPI, long archivedDate, int startIndex, int maxResults){
processAPI.searchArchivedDocuments(new SearchOptionsBuilder(startIndex, maxResults).with {
lessOrEquals(ArchivedDocumentsSearchDescriptor.ARCHIVE_DATE, archivedDate)
done()
})
}
//Delete archived documents older than archivedDate
def deleteArchivedDocumentsOlderThan(ProcessAPI processAPI, long archivedDate) {
int startIndex = 0
int maxResults = 100
def searchResult = searchArchivedDocumentsOlderThanArchivedDate(processAPI, archivedDate, startIndex, maxResults)
while(searchResult.count > 0){
searchResult.result.each { archivedDocument ->
processAPI.deleteContentOfArchivedDocument(archivedDocument.getId())
}
startIndex += maxResults
searchResult = searchArchivedDocumentsOlderThanArchivedDate(processAPI, archivedDate, startIndex, maxResults)
}
}
//Then just call the method with desired archivedDate
deleteArchivedDocumentsOlderThan(processAPI, archivedDate)