Skip to content

Annotation to hydrate collection fields as thread-safe collections on load #138

Description

@jtnelson

Problem

When Runway loads a record, it replaces each collection field with a
plain ArrayList (or LinkedHashSet), discarding any thread-safe
collection the field was initialized with. A field declared as, for
example, Collections.synchronizedList(...) or a CopyOnWriteArrayList
is therefore thread-safe only on a freshly constructed record; once
loaded, it is a non-thread-safe collection again.

Models that need a thread-safe collection currently work around this by
re-wrapping the field in onLoad(). That is easy to forget and is
duplicated across every model that needs it.

Additional consideration

The save path iterates a record's collection fields directly (to
serialize links and enforce constraints) without synchronizing on the
collection. As a result, Collections.synchronizedList is not
sufficient on its own: it guards individual operations but not
iteration, so a concurrent structural modification during a save can
still raise ConcurrentModificationException. A safe default therefore
needs to be iteration-safe under concurrent modification (such as
CopyOnWriteArrayList), or the save path needs to snapshot or
synchronize the collection while iterating it.

Proposal

Provide a field-level annotation (for example @ThreadSafe or
@Concurrent) that instructs Runway to hydrate the annotated collection
field into a thread-safe, iteration-safe collection on load, so a model
no longer needs bespoke onLoad() handling to keep a collection safe
for concurrent access.

Acceptance

  • A collection field marked with the annotation is backed by a
    thread-safe, iteration-safe collection after a record is loaded, with
    no manual onLoad() wrapping.
  • Concurrent structural modification during a save does not raise
    ConcurrentModificationException.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions