Skip to content

Downgrade Java target from 21 to 17 and remove Records for Android compatibility #1512

@aslan564

Description

@aslan564

Problem

OpenPDF 3.0.x targets Java 21 and uses several Java 21+ features that cause
compatibility issues for downstream consumers:

  1. Java Records (28 usages across 15 files) — Android's D8/R8 desugaring
    cannot handle java.lang.Record without explicit global-synthetics
    consumer configuration (AGP 8.3+). This causes build failures for Android
    SDK developers who depend on OpenPDF:

  2. Virtual Threads (Executors.newVirtualThreadPerTaskExecutor()) —
    Java 21 only, excludes Java 17 LTS users.

  3. SequencedCollection methods (getFirst(), getLast() on List) —
    Java 21 only.

Many enterprise environments and Android projects still target Java 17 LTS.
Supporting Java 17 as the minimum version would significantly expand
OpenPDF's compatibility.

Changes

Java version: 21 → 17

  • pom.xml: Changed <java.version> from 21 to 17

Virtual Threads → CachedThreadPool (1 file)

  • PdfBatch.java: Replaced newVirtualThreadPerTaskExecutor() with
    newCachedThreadPool() + proper shutdown() in finally block

SequencedCollection methods (2 files)

  • PdfContentStreamHandler.java: getLast()get(size()-1),
    getFirst()get(0)
  • PdfTextLocator.java: getLast()get(size()-1)

Java Records → Regular classes (15 files, 28 records)

openpdf-core:

  • PdfBatchUtils.java: MergeJob, WatermarkJob, EncryptJob, SplitJob

openpdf-html:

  • HtmlToPdfBatchUtils.java: HtmlStringJob, HtmlFileJob, UrlJob
  • JustificationInfo.java, FontDescription.java (Decorations),
    HSBColor.java, CSSName.java (CSSSideProperties)
  • BorderPropertySet.java: Styles, Colors, Corners
  • BorderRadiusCorner.java: Length
  • FloatManager.java: BoxOffset, BoxDistance
  • PageBox.java: PageDimensions, MarginAreaContainer
  • InlineBoxing.java: StaticFloatDistances, DynamicFloatDistances
  • DefaultLineBreakingStrategy.java: DefaultBreakPointsProvider
  • DocumentSplitter.java: ProcessingInstruction
  • SelectField.java: NameValuePair
  • SwingReplacedElementFactory.java: CacheKey
  • ImageResourceLoader.java: CacheKey

All replacement classes provide:

  • public final fields (for direct access compatibility)
  • Accessor methods matching record naming convention (e.g., input() not getInput())
  • equals()/hashCode()/toString() where needed (HashMap keys, test assertions)

Test fixes

  • Removed Thread.isVirtual() assertions (Java 21 API)
  • Added platform-safe font handling in FontTest for macOS Courier.ttc

Verification

  • BUILD SUCCESS — all 2264 tests pass (0 failures, 0 errors)
  • Zero java.lang.Record references in compiled bytecode
    (verified via grep -l "java/lang/Record" on all .class files)
  • Full backward API compatibility maintained

Impact

This change allows OpenPDF to be used by:

  • Java 17 LTS environments
  • Android projects without desugaring configuration
  • SDK developers who bundle OpenPDF as a transitive dependency

Your real name
Aslan Aslanov

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions