Skip to content
Open
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
5814e6e
Initial plan
Copilot Oct 7, 2025
0fcd021
Complete migration compatibility report and guides
Copilot Oct 7, 2025
64fe4e7
Add migration summary document
Copilot Oct 7, 2025
d46d290
Add migration documentation index
Copilot Oct 7, 2025
744f935
Start Play 3.0.5 + Pekko 1.0.2 upgrade implementation
Copilot Oct 9, 2025
390a78d
Update all POM files for Play 3.0.5 + Pekko 1.0.2
Copilot Oct 9, 2025
4c87416
Migrate all Java source files from Akka to Pekko
Copilot Oct 9, 2025
de20668
Fix POM dependencies for Play 3.0.5 compatibility
Copilot Oct 9, 2025
7c70c3c
Fix Play 3.0 API compatibility - BUILD SUCCESSFUL
Copilot Oct 9, 2025
0ec3485
Add implementation summary - upgrade complete
Copilot Oct 9, 2025
1bd3f0c
Fix test files: Replace JavaTestKit.duration() with java.time.Duration
Copilot Oct 9, 2025
ebca0e9
Fix Duration ambiguity in test files
Copilot Oct 9, 2025
55a8472
Fix missing Duration imports in test files
Copilot Oct 9, 2025
10cdc0e
Fix ActorStartModule: Restore Pekko actor bindings for Guice DI
Copilot Oct 9, 2025
521d323
Fix Scala 2.12/2.13 conflict: Exclude Scala 2.12 from cloud-store-sdk
Copilot Oct 9, 2025
4a6bf0e
Fix Scala 2.12/2.13 conflict in controller: Exclude all Scala 2.12 tr…
Copilot Oct 9, 2025
e236781
Final: Add UPGRADE_COMPLETE.md - Migration successfully finished
Copilot Oct 9, 2025
fc8da5e
changes after testing
Oct 10, 2025
d10ae89
Merge branch 'copilot/upgrade-play-framework-and-switch-to-pekko' of …
Oct 10, 2025
679513a
Addressing PR comments
Copilot Oct 10, 2025
33c3a67
Delete IMPLEMENTATION_SUMMARY.md
sntiwari1 Oct 10, 2025
c096eff
Docs update
Oct 10, 2025
6180ada
Readme updated
Oct 10, 2025
1fe3a0f
Complete Upgrade: Play Framework 3.0.5 + Apache Pekko 1.0.2 Migration
sntiwari1 Oct 10, 2025
16e698b
refactor: Refactor RequestMapper to use ObjectMapper for JSON convers…
chethann007 Oct 30, 2025
c6324b4
refactor: Update references from Akka to Pekko in configuration and d…
chethann007 Oct 30, 2025
cb721b3
Merge pull request #2 from chethann-007/release-8.0.0
sntiwari1 Oct 30, 2025
8a29128
Fix typo in Environment Variables section
sntiwari1 Nov 4, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
111 changes: 111 additions & 0 deletions UPGRADE_README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
# Play Framework 3.0.5 and Apache Pekko 1.0.2 Upgrade

## Overview

This document describes the upgrade of userorg-service from Play Framework 2.7.2 with Akka 2.5.22 to Play Framework 3.0.5 with Apache Pekko 1.0.2.

## Why This Upgrade

1. License Compliance: Akka changed from Apache 2.0 to Business Source License 1.1, requiring commercial licenses for production use. Apache Pekko maintains Apache 2.0 license.
2. Security: Play 2.7.2 and Akka 2.5.22 no longer receive security updates.
3. Modernization: Access to latest features and performance improvements.

## Technology Stack Changes

- Play Framework: 2.7.2 to 3.0.5
- Actor Framework: Akka 2.5.22 to Apache Pekko 1.0.2
- Scala: 2.12.11 to 2.13.12
- Guice: 3.0 to 5.1.0
- SLF4J: 1.6.1 to 2.0.9
- Logback: 1.2.3 to 1.4.14
- Jackson: 2.13.5 to 2.14.3
- Netty: 4.1.44 to 4.1.93

## Key Changes

### Dependencies

All Maven POM files updated with new versions. Play Framework groupId changed from com.typesafe.play to org.playframework. Scala library exclusions added to prevent version conflicts between Scala 2.12 and 2.13.

### Source Code

329 Akka imports migrated to Pekko across 130+ Java files:
- akka.actor.* to org.apache.pekko.actor.*
- akka.pattern.* to org.apache.pekko.pattern.*
- akka.routing.* to org.apache.pekko.routing.*
- akka.util.* to org.apache.pekko.util.*
- akka.testkit.* to org.apache.pekko.testkit.*

### Configuration

application.conf files updated with Pekko namespaces:
- akka {} to pekko {}
- Actor system configurations migrated
- Serialization bindings updated
- Dispatcher references changed

### Play 3.0 API Updates

- ActorStartModule: Implements play.libs.pekko.PekkoGuiceSupport
- CustomGzipFilter: Updated to Play 3.0 filter API
- ErrorHandler: Migrated exception handling to Pekko

### Test Framework

38+ test files updated:
- Replaced JavaTestKit.duration() with java.time.Duration.ofSeconds()
- Resolved Duration class ambiguity between java.time and scala.concurrent
- Fixed import conflicts

### Scala Version Conflicts

Added exclusions to prevent Scala 2.12 transitive dependencies:
- Excluded scala-library and scala-reflect from cloud-store-sdk in platform-common
- Excluded scala-library and scala-reflect from platform-common and service dependencies in controller
- Explicitly declared scala-library 2.13.12 dependency

## Build Instructions

Build all modules:
```
mvn clean install -Dmaven.test.skip=true
```

Build with test compilation:
```
mvn clean install -DskipTests
```

Create distribution package:
```
cd controller
mvn play2:dist
```

## Migration Impact

Business Logic: No changes to business logic or functionality
API Compatibility: Maintained, as Pekko is API-compatible with Akka 2.6
Code Changes: Primarily package name updates from akka to pekko
License: Now compliant with Apache 2.0 throughout the stack

## Testing Recommendations

1. Execute full unit test suite
2. Run integration tests for actor communication
3. Perform regression testing for all features
4. Conduct performance benchmarking
5. Test under production-like load

## Files Modified

- POM files
- Java source files
- configuration files
- test files

## Known Issues

Scala 2.12/2.13 Conflict: If you encounter NoClassDefFoundError for scala.collection.GenMap, verify dependency tree to ensure no Scala 2.12 artifacts are present. Run mvn dependency:tree and add exclusions for any scala-library or scala-reflect with version 2.12.

Play 3 will automatically apply gzip based on the Accept-Encoding header. You don’t need a custom Java filter.
14 changes: 7 additions & 7 deletions controller/app/controllers/BaseController.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
import static util.PrintEntryExitLog.printExitLogOnFailure;
import static util.PrintEntryExitLog.printExitLogOnSuccessResponse;

import akka.actor.ActorRef;
import akka.actor.ActorSelection;
import akka.pattern.PatternsCS;
import akka.util.Timeout;
import org.apache.pekko.actor.ActorRef;
import org.apache.pekko.actor.ActorSelection;
import org.apache.pekko.pattern.PatternsCS;
import org.apache.pekko.util.Timeout;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
Expand Down Expand Up @@ -62,9 +62,9 @@ public class BaseController extends Controller {
private static final LoggerUtil logger = new LoggerUtil(BaseController.class);

private static final ObjectMapper objectMapper = new ObjectMapper();
public static final int AKKA_WAIT_TIME = 30;
public static final int PEKKO_WAIT_TIME = 30;
private static final String version = "v1";
protected Timeout timeout = new Timeout(AKKA_WAIT_TIME, TimeUnit.SECONDS);
protected Timeout timeout = new Timeout(PEKKO_WAIT_TIME, TimeUnit.SECONDS);
private static final String debugEnabled = "false";

private org.sunbird.request.Request initRequest(
Expand Down Expand Up @@ -680,7 +680,7 @@ private static long calculateApiTimeTaken(Long startTime) {
}

/**
* This method will make a call to Akka actor and return CompletionStage.
* This method will make a call to Pekko actor and return CompletionStage.
*
* @param actorRef ActorSelection
* @param request Request
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package controllers.bulkapimanagement;

import akka.actor.ActorRef;
import org.apache.pekko.actor.ActorRef;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
Expand Down
2 changes: 1 addition & 1 deletion controller/app/controllers/feed/FeedController.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package controllers.feed;

import akka.actor.ActorRef;
import org.apache.pekko.actor.ActorRef;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potential DI incompatibility between Akka and Pekko ActorRef category Functionality

Tell me more
What is the issue?

The import has been changed from Akka to Apache Pekko, but the injected ActorRef field may not be compatible if the dependency injection configuration still references Akka actors.

Why this matters

If the dependency injection framework is still configured to inject Akka ActorRef instances while the code expects Pekko ActorRef instances, this will cause runtime failures when the application tries to inject the userFeedActor dependency.

Suggested change ∙ Feature Preview

Ensure that the dependency injection configuration (likely in application.conf or a DI module) has been updated to create and inject Pekko ActorRef instances instead of Akka ones. Verify that the "user_feed_actor" binding creates a Pekko actor, not an Akka actor.

Provide feedback to improve future suggestions

Nice Catch Incorrect Not in Scope Not in coding standard Other

💬 Looking for more details? Reply to this comment to chat with Korbit.

import controllers.BaseController;
import controllers.feed.validator.FeedRequestValidator;
import java.util.concurrent.CompletionStage;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/** */
package controllers.healthmanager;

import akka.actor.ActorRef;
import org.apache.pekko.actor.ActorRef;
import controllers.BaseController;
import java.util.ArrayList;
import java.util.HashMap;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package controllers.location;

import akka.actor.ActorRef;
import org.apache.pekko.actor.ActorRef;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potential runtime incompatibility between Akka and Pekko ActorRef category Functionality

Tell me more
What is the issue?

The import change from Akka to Apache Pekko may cause runtime compatibility issues if the rest of the codebase still uses Akka actors or if the injected locationActor is still an Akka ActorRef.

Why this matters

This could lead to ClassCastException or NoClassDefFoundError at runtime when the dependency injection framework tries to inject an Akka ActorRef into a field expecting a Pekko ActorRef, or when the actor system tries to communicate between different actor implementations.

Suggested change ∙ Feature Preview

Ensure that the entire actor system has been migrated to Pekko consistently. Verify that:

  1. The locationActor bean definition uses Pekko ActorRef
  2. All actor system configurations use Pekko
  3. The BaseController and actorResponseHandler method are compatible with Pekko ActorRef

Example verification:

// Ensure the injected actor is Pekko-based
@Inject
@Named("location_actor")
private org.apache.pekko.actor.ActorRef locationActor;
Provide feedback to improve future suggestions

Nice Catch Incorrect Not in Scope Not in coding standard Other

💬 Looking for more details? Reply to this comment to chat with Korbit.

import com.fasterxml.jackson.databind.JsonNode;
import controllers.BaseController;
import java.util.Map;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package controllers.notesmanagement;

import akka.actor.ActorRef;
import org.apache.pekko.actor.ActorRef;
import com.fasterxml.jackson.databind.JsonNode;
import controllers.BaseController;
import controllers.notesmanagement.validator.NoteRequestValidator;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package controllers.notificationservice;

import akka.actor.ActorRef;
import org.apache.pekko.actor.ActorRef;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import controllers.BaseController;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package controllers.organisationmanagement;

import akka.actor.ActorRef;
import org.apache.pekko.actor.ActorRef;
import controllers.BaseController;
import java.util.concurrent.CompletionStage;
import javax.inject.Inject;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package controllers.organisationmanagement;

import akka.actor.ActorRef;
import org.apache.pekko.actor.ActorRef;
import controllers.BaseController;
import java.util.concurrent.CompletionStage;
import javax.inject.Inject;
Expand Down
2 changes: 1 addition & 1 deletion controller/app/controllers/otp/OtpController.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package controllers.otp;

import akka.actor.ActorRef;
import org.apache.pekko.actor.ActorRef;
import controllers.BaseController;
import controllers.otp.validator.OtpRequestValidator;
import java.util.concurrent.CompletionStage;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package controllers.storage;

import akka.actor.ActorRef;
import org.apache.pekko.actor.ActorRef;
import com.fasterxml.jackson.databind.JsonNode;
import controllers.BaseController;
import java.io.ByteArrayInputStream;
Expand Down
2 changes: 1 addition & 1 deletion controller/app/controllers/sync/SyncController.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/** */
package controllers.sync;

import akka.actor.ActorRef;
import org.apache.pekko.actor.ActorRef;
import com.fasterxml.jackson.databind.JsonNode;
import controllers.BaseController;
import java.util.HashMap;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package controllers.systemsettings;

import akka.actor.ActorRef;
import org.apache.pekko.actor.ActorRef;
import controllers.BaseController;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
Expand Down
2 changes: 1 addition & 1 deletion controller/app/controllers/tac/UserTnCController.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package controllers.tac;

import akka.actor.ActorRef;
import org.apache.pekko.actor.ActorRef;
import controllers.BaseController;
import controllers.tac.validator.UserTnCRequestValidator;
import java.util.concurrent.CompletionStage;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package controllers.tenantmigration;

import akka.actor.ActorRef;
import org.apache.pekko.actor.ActorRef;
import controllers.BaseController;
import java.util.concurrent.CompletionStage;
import javax.inject.Inject;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package controllers.tenantpreference;

import akka.actor.ActorRef;
import org.apache.pekko.actor.ActorRef;
import controllers.BaseController;
import java.util.concurrent.CompletionStage;
import javax.inject.Inject;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package controllers.usermanagement;

import akka.actor.ActorRef;
import org.apache.pekko.actor.ActorRef;
import controllers.BaseController;
import java.util.concurrent.CompletionStage;
import javax.inject.Inject;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package controllers.usermanagement;

import akka.actor.ActorRef;
import org.apache.pekko.actor.ActorRef;
import controllers.BaseController;
import controllers.usermanagement.validator.ResetPasswordRequestValidator;
import java.util.concurrent.CompletionStage;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package controllers.usermanagement;

import akka.actor.ActorRef;
import org.apache.pekko.actor.ActorRef;
import controllers.BaseController;
import controllers.usermanagement.validator.UserConsentRequestValidator;
import java.util.concurrent.CompletionStage;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package controllers.usermanagement;

import akka.actor.ActorRef;
import org.apache.pekko.actor.ActorRef;
import controllers.BaseController;
import controllers.usermanagement.validator.UserGetRequestValidator;
import java.util.HashMap;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package controllers.usermanagement;

import akka.actor.ActorRef;
import org.apache.pekko.actor.ActorRef;
import controllers.BaseController;
import java.util.concurrent.CompletionStage;
import javax.inject.Inject;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package controllers.usermanagement;

import akka.actor.ActorRef;
import org.apache.pekko.actor.ActorRef;
import controllers.BaseController;
import java.util.Optional;
import java.util.concurrent.CompletionStage;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package controllers.usermanagement;

import akka.actor.ActorRef;
import org.apache.pekko.actor.ActorRef;
import controllers.BaseController;
import controllers.usermanagement.validator.UserRoleRequestValidator;
import java.util.concurrent.CompletionStage;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package controllers.usermanagement;

import akka.actor.ActorRef;
import org.apache.pekko.actor.ActorRef;
import controllers.BaseController;
import controllers.usermanagement.validator.UserStatusRequestValidator;
import java.util.concurrent.CompletionStage;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package controllers.usermanagement;

import akka.actor.ActorRef;
import org.apache.pekko.actor.ActorRef;
import controllers.BaseController;
import java.util.concurrent.CompletionStage;
import javax.inject.Inject;
Expand Down
2 changes: 1 addition & 1 deletion controller/app/filters/AccessLogFilter.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package filters;

import akka.util.ByteString;
import org.apache.pekko.util.ByteString;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unverified API compatibility in library migration category Functionality

Tell me more
What is the issue?

The import has been changed from Akka to Apache Pekko ByteString, but there's no verification that the Pekko ByteString API is fully compatible with the existing usage in the filter logic.

Why this matters

If the Apache Pekko ByteString implementation has different behavior or API differences compared to Akka's ByteString, this could cause runtime failures or unexpected behavior in the accumulator processing, potentially breaking request/response handling.

Suggested change ∙ Feature Preview

Verify that Apache Pekko's ByteString is API-compatible with Akka's ByteString for the usage patterns in this filter. Test the filter functionality thoroughly after the migration to ensure request processing and accumulator behavior remains unchanged. Consider adding integration tests that verify the filter processes requests correctly with the new dependency.

Provide feedback to improve future suggestions

Nice Catch Incorrect Not in Scope Not in coding standard Other

💬 Looking for more details? Reply to this comment to chat with Korbit.

import java.util.concurrent.Executor;
import javax.inject.Inject;
import play.libs.streams.Accumulator;
Expand Down
Loading