Skip to main content
Version: v2026.0.0

XFDF file annotation storage

ARender stores annotations as XFDF files on the local filesystem by default. Each document gets one .xml file whose name is derived from the document identifier. No additional connector JAR or database schema is required.

When to use this guide

Use this guide when you are deploying a single ARender UI instance and need a simple, zero-dependency annotation storage, or when you want to understand the default behavior before switching to a different backend. File-based storage is appropriate for development, single-node production deployments, and cases where annotation data lives on a shared network volume.

For multi-instance deployments where all UI nodes must share the same annotation set, consider JDBC annotation storage instead.

How it works

The XFDFAnnotationAccessor bean delegates all read and write operations to a FileSerializedContentAccessor. When a document is opened, ARender looks for a file at:

<storage-path>/<document-id>.xml

The document identifier is sanitized before use: forward slashes (/) and equals signs (=) are replaced with underscores so the result is a valid filename. For example, a document with ID contracts/2024/doc_001 produces the file contracts_2024_doc_001.xml.

When no file exists for a document, ARender returns an empty annotation set and creates the file on the first save.

Configuration properties reference

PropertyDescriptionDefault
arender.server.annotations.xfdf.localstorage.default.pathFilesystem path where XFDF annotation files are stored. Trailing slash required.~/ARenderAnnotations/
arender.server.annotations.can.createWhether users can create new annotationstrue
arender.server.annotations.text.html.supportWhether text annotations allow HTML content stylingtrue
arender.server.annotations.text.reply.supportWhether users can reply to text annotationstrue
arender.server.annotations.text.status.supportWhether text annotations support status trackingtrue
arender.server.annotations.text.comment.reply.supportWhether comment threads support repliestrue
arender.server.annotations.text.security.supportWhether annotations can have security classification levelsfalse

File format

Each file is an XFDF document (XML). ARender reads and writes the full annotation set for a document in a single pass. Annotations are stored by their name attribute; updates replace the matching entry in the serialized XML before rewriting the file.

An example file for a document with two annotations looks like:

<?xml version="1.0" encoding="UTF-8"?>
<xfdf xmlns="http://ns.adobe.com/xfdf/" xml:space="preserve">
<annots>
<square name="annot-1" page="0" rect="100,200,300,400" color="#ff0000" title="alice" date="D:20240315120000" />
<highlight name="annot-2" page="1" rect="50,100,250,120" color="#ffff00" title="bob" date="D:20240315130000" />
</annots>
</xfdf>

Shared volume requirements

Because each viewer instance reads and writes annotation files directly, all instances must access the same storage path. In a containerized deployment, mount a shared volume at the annotation path.

caution

The FileSerializedContentAccessor does not apply any locking across process boundaries. If two replicas write to the same file at the same time, one write may overwrite the other. For multi-replica deployments under concurrent annotation load, use JDBC or REST annotation storage instead.

Troubleshooting

Annotations are not saved: verify that the process user has write permission on the storage directory. Enable debug logging on com.arondor.viewer.xfdf.annotation to trace the exact file path being written.

Annotations disappear after container restart: the storage path is inside the container. Mount a persistent volume at that path.

Unexpected file names: the document identifier string is sanitized by replacing / and = with _. If your document IDs contain other special characters, check the resulting filename manually to confirm the mapping.