You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@pekko.apache.org by "pjfanning (via GitHub)" <gi...@apache.org> on 2026/08/27 09:14:14 UTC

[PR] fix: make AbstractPersistentActorWithTimers and AbstractFSMWithStash subclassable from Java on Scala 3 [pekko]

pjfanning opened a new pull request, #3475:
URL: https://github.com/apache/pekko/pull/3475

   ### Motivation
   
   Extending `AbstractPersistentActorWithTimers` from Java fails to compile against the Scala 3 artifacts:
   
   ```
   TestActor.java:[5,8] types org.apache.pekko.actor.Timers and org.apache.pekko.persistence.Eventsourced are incompatible;
     class TestActor inherits unrelated defaults for aroundPreRestart(java.lang.Throwable,scala.Option<java.lang.Object>)
     from types org.apache.pekko.actor.Timers and org.apache.pekko.persistence.Eventsourced
   ```
   
   Both `Timers` and `Eventsourced` implement `aroundReceive`, `aroundPreRestart` and `aroundPostStop`. Scala 3 *does* emit the mixin forwarder into the class, but flags it `ACC_BRIDGE, ACC_SYNTHETIC`:
   
   ```
   public void aroundPreRestart(java.lang.Throwable, scala.Option);
     flags: (0x1041) ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC
   ```
   
   javac ignores synthetic and bridge members when resolving inherited members, so it falls back to the two interface defaults and rejects the subclass. Scala 2.13 emits the same forwarder without those flags, which is why the 2.12/2.13 artifacts work. This is accidental, not a deliberate limitation.
   
   The reporter asked whether other multi-trait base classes are affected. I compiled a javac probe (an abstract Java subclass) against the Scala 3 build output for every Java-facing `Abstract*`/`UntypedAbstract*` class that mixes in more than one trait — the stash, logging and timers variants, `AbstractLoggingFSM`, `AbstractFSMWithStash`, `AbstractPersistentActor`, `AbstractPersistentActorWithTimers`, `AbstractPersistentActorWithAtLeastOnceDelivery`, `AbstractPersistentFSM`, `AbstractPersistentLoggingFSM`, `journal.japi.AsyncWriteJournal`, `AbstractInOutHandler` and `AbstractSerializationSupport`. Exactly one other class has the same defect: `AbstractFSMWithStash`, where `FSM` and `UnrestrictedStash` both implement `postStop`.
   
   ### Modification
   
   Give both classes real (non-synthetic) overrides of the conflicting members that simply delegate to `super`, which resolves exactly like the forwarders they replace, so behaviour is unchanged on both Scala versions.
   
   `AbstractFSMWithStash.postStop` deliberately carries no `@throws(classOf[Exception])`: `FSM.postStop` declares no checked exceptions, and a wider throws clause is not a valid override for javac.
   
   Added Java sources exercising both classes, so the Scala 3 build fails if this regresses:
   
   - `persistence/src/test/java/.../JavaTimerPersistentActor.java`, driven by a new case in `TimerPersistentActorSpec`
   - `actor-tests/src/test/java/.../AbstractFSMWithStashActorTest.java`, a JUnit 5 test
   
   ### Result
   
   Java subclasses of `AbstractPersistentActorWithTimers` and `AbstractFSMWithStash` compile against the Scala 3 artifacts. No other Java-facing multi-trait base class in the build is affected.
   
   ### Tests
   
   - `sbt "++3.3.8" "persistence/testOnly org.apache.pekko.persistence.TimerPersistentActorSpec"` — 5 succeeded, 0 failed
   - `sbt "++3.3.8" "actor-tests/testOnly org.apache.pekko.actor.AbstractFSMWithStashActorTest org.apache.pekko.actor.AbstractFSMActorTest"` — 2 succeeded, 0 failed
   - `sbt "persistence/testOnly org.apache.pekko.persistence.TimerPersistentActorSpec"` (2.13) — 5 succeeded, 0 failed
   - `sbt "actor-tests/testOnly org.apache.pekko.actor.AbstractFSMWithStashActorTest org.apache.pekko.actor.AbstractFSMActorTest"` (2.13) — 2 succeeded, 0 failed
   - `sbt headerCreateAll javafmtAll scalafmtAll scalafmtSbt` on JDK 17 — headers generated by sbt, no formatting churn outside the changed files
   - `sbt +mimaReportBinaryIssues` — Not run locally, left to the CI `Check / Binary Compatibility` job
   
   Both Java test sources fail to compile under Scala 3 without the corresponding production change, and compile once it is applied.
   
   ### References
   
   Fixes #3474


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@pekko.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@pekko.apache.org
For additional commands, e-mail: notifications-help@pekko.apache.org


Re: [PR] fix: make AbstractPersistentActorWithTimers and AbstractFSMWithStash subclassable from Java on Scala 3 [pekko]

Posted by "pjfanning (via GitHub)" <gi...@apache.org>.
pjfanning merged PR #3475:
URL: https://github.com/apache/pekko/pull/3475


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@pekko.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@pekko.apache.org
For additional commands, e-mail: notifications-help@pekko.apache.org