DEV Community

Leon Davis
Leon Davis

Posted on

How to Make PDF Form Fields Read-Only or Flatten Them in Java

Once a PDF form has been completed, you may want to prevent further edits without losing the form structure, or remove the interactive fields entirely and produce a final version for delivery or archiving.

These two requirements are usually handled differently. A read-only field remains part of the PDF form and can still be accessed programmatically, while a flattened field is converted into static page content.

This article shows how to make an entire PDF form or an individual field read-only, how to flatten all or selected fields, and when each approach is more appropriate.

Add the Dependency

The examples below use Spire.PDF for Java to work with PDF forms. For Maven projects, add the following repository and dependency to pom.xml:

<repositories>
    <repository>
        <id>com.e-iceblue</id>
        <name>e-iceblue</name>
        <url>https://repo.e-iceblue.com/nexus/content/groups/public/</url>
    </repository>
</repositories>

<dependencies>
    <dependency>
        <groupId>e-iceblue</groupId>
        <artifactId>spire.pdf</artifactId>
        <version>12.8.6</version>
    </dependency>
</dependencies>
Enter fullscreen mode Exit fullscreen mode

Make an Entire PDF Form Read-Only

If the field values still need to be available to later code but users should no longer be able to change them, keep the form structure and mark the form as read-only.

Use PdfFormWidget.setReadOnly() to apply the setting to all fields:

import com.spire.pdf.PdfDocument;
import com.spire.pdf.widget.PdfFormWidget;

public class SetFormReadOnly {
    public static void main(String[] args) {

        // Load the PDF form
        PdfDocument pdf = new PdfDocument();
        pdf.loadFromFile("ApplicationForm.pdf");

        // Make all form fields read-only
        PdfFormWidget form = (PdfFormWidget) pdf.getForm();
        form.setReadOnly(true);

        // Save the result
        pdf.saveToFile("ApplicationForm_ReadOnly.pdf");
        pdf.close();
    }
}
Enter fullscreen mode Exit fullscreen mode

The fields remain in the PDF after this operation, so the application can still retrieve their names and values or perform other form-related processing later.

Make a Specific PDF Form Field Read-Only

To lock only one field, retrieve the corresponding PdfField and call setReadOnly() on it:

import com.spire.pdf.PdfDocument;
import com.spire.pdf.fields.PdfField;
import com.spire.pdf.widget.PdfFormWidget;

public class SetFieldReadOnly {
    public static void main(String[] args) {

        PdfDocument pdf = new PdfDocument();
        pdf.loadFromFile("ApplicationForm.pdf");

        PdfFormWidget form = (PdfFormWidget) pdf.getForm();

        // Get the field by its internal name
        PdfField field = form.getFieldsWidget().get("RequestAmount");

        if (field != null) {
            field.setReadOnly(true);
        }

        pdf.saveToFile("ApplicationForm_PartiallyReadOnly.pdf");
        pdf.close();
    }
}
Enter fullscreen mode Exit fullscreen mode

One detail that matters in real projects is that the name used in code is the field's internal PDF name, not necessarily the label visible on the page.

A field displayed as Request Amount, for example, may internally be named:

RequestAmount
amount
TextField12
Enter fullscreen mode Exit fullscreen mode

If the template comes from another team or an external source, inspect the available field names first:

PdfFormWidget form = (PdfFormWidget) pdf.getForm();

for (int i = 0; i < form.getFieldsWidget().getCount(); i++) {
    PdfField field = form.getFieldsWidget().get(i);
    System.out.println(field.getName());
}
Enter fullscreen mode Exit fullscreen mode

For templates that change over time, field names are also safer than hard-coded indexes. Once fields are added or reordered, an index may point to a different field without making the problem immediately obvious.

Flatten All PDF Form Fields

When the PDF no longer needs to behave as an interactive form, the fields can be flattened.

Use isFlatten(true) to flatten the entire form:

import com.spire.pdf.PdfDocument;

public class FlattenForm {
    public static void main(String[] args) {

        // Load the completed PDF form
        PdfDocument pdf = new PdfDocument();
        pdf.loadFromFile("ApprovedForm.pdf");

        // Flatten all form fields
        pdf.getForm().isFlatten(true);

        // Save the result
        pdf.saveToFile("ApprovedForm_Flattened.pdf");
        pdf.close();
    }
}
Enter fullscreen mode Exit fullscreen mode

The current appearance of each field is preserved on the page, but text boxes, check boxes, drop-down lists, and other interactive controls are no longer available as fillable fields.

Any logic that still depends on the form structure should therefore run before flattening. This includes reading values, assigning data, validating fields, and exporting form data.

Flatten a Specific PDF Form Field

You can also flatten a single field while leaving the rest of the form interactive.

Retrieve the target PdfField and call setFlatten(true):

import com.spire.pdf.PdfDocument;
import com.spire.pdf.fields.PdfField;
import com.spire.pdf.widget.PdfFormWidget;

public class FlattenField {
    public static void main(String[] args) {

        PdfDocument pdf = new PdfDocument();
        pdf.loadFromFile("ApplicationForm.pdf");

        PdfFormWidget form = (PdfFormWidget) pdf.getForm();

        // Get the target field
        PdfField field = form.getFieldsWidget().get("RequestAmount");

        if (field != null) {
            field.setFlatten(true);
        }

        pdf.saveToFile("ApplicationForm_PartiallyFlattened.pdf");
        pdf.close();
    }
}
Enter fullscreen mode Exit fullscreen mode

This is useful when one part of a form is final but other fields still need to remain editable.

Checking for null is worth keeping in production code. PDF templates are often updated independently of the application, and a renamed or removed field can otherwise turn a simple template change into a NullPointerException.

Read-Only vs. Flattened Form Fields

Both approaches can stop normal user input, but they leave the PDF in very different states.

Aspect Read-Only Flattened
Interactive field structure preserved Yes No
User can edit the field normally No No
Field can still be accessed by name Yes No longer appropriate
Field properties can be changed later Yes No
Suitable for ongoing form processing Yes Usually not
Suitable for final delivery or archiving Yes Usually better

Use read-only fields when the PDF is still part of a larger workflow and your code may need to inspect or process the form later.

Flatten the fields when the form itself is no longer needed and only the final rendered content matters.

Neither option should be treated as a PDF security feature. Setting a field to read-only or flattening it does not prevent the whole document from being edited, copied, or printed. Those requirements belong to PDF permission settings, while tamper detection is better handled with digital signatures.

Practical Considerations

For fixed templates, field names are generally more reliable than field indexes. If templates are maintained outside the development team, it is useful to inspect the internal field names during integration and keep those names in configuration or constants rather than scattering them throughout the codebase.

Flattening should also be one of the last steps in the processing pipeline. Once a final flattened file has been produced, later code should not assume that the original form structure is still available.

The rendered result deserves a quick check as well, especially when the form contains CJK text, custom fonts, symbols, check boxes, or drop-down fields. A server may not have the same fonts as a developer workstation, and that difference can affect how field content appears after flattening.

Conclusion

For production systems, keep the editable source form separate from the generated read-only or flattened output. That small separation makes template updates, data corrections, and troubleshooting much easier than trying to recover structure from a file that has already been finalized.

Top comments (0)