Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
9891274
Merge branch 'release-5.0.0' of github.com:Sunbird-Lern/certificate-r…
reshmi-nair Aug 26, 2022
62ae844
LR-267 CSP related changes
prasadmoka Nov 8, 2022
803f6cb
Merge pull request #100 from prasadmoka/local-5.0.0
reshmi-nair Nov 14, 2022
69b24dc
fixed the Vulnerability
divyagovindaiah Jun 20, 2025
0ac282b
Merge branch 'Sunbird-Lern:master' into release-5.0.0_RC1-vuln-fix
divyagovindaiah Jun 23, 2025
f939f5f
Update Dockerfile
divyagovindaiah Jun 23, 2025
3429add
Merge pull request #110 from divyagovindaiah/release-5.0.0_RC1-vuln-fix
pallakartheekreddy Jun 24, 2025
d2b788c
#SBCOSS-607 fix: vulnerability fixes
chethann007 Sep 8, 2025
4c94236
#SBCOSS-607 fix: vulnerability fixes
chethann007 Sep 8, 2025
a2b9057
#SBCOSS-607 fix: vulnerability fixes
chethann007 Sep 8, 2025
31f8cab
#SBCOSS-607 fix: vulnerability fixes
chethann007 Sep 8, 2025
609f3cc
Merge pull request #111 from Sunbird-Lern/vuln-fixes
pallakartheekreddy Sep 8, 2025
3126692
feat: adding github actions
chethann007 Sep 8, 2025
b190aa9
feat: adding github actions
chethann007 Sep 8, 2025
f8ac384
Merge pull request #112 from Sunbird-Lern/gh-actions
pallakartheekreddy Sep 8, 2025
9329797
Initial plan
Copilot Oct 7, 2025
69b19d7
Add comprehensive Play Framework & Akka to Pekko migration analysis
Copilot Oct 7, 2025
d3968e7
Add START_HERE.md navigation guide for migration documentation
Copilot Oct 7, 2025
90e4d6e
Upgrade to Play Framework 3.0.5 and Apache Pekko 1.0.2
Copilot Oct 10, 2025
f95877e
Add comprehensive upgrade summary documentation
Copilot Oct 10, 2025
a4dcf75
Local changes
Oct 10, 2025
348febd
Replace multiple documentation files with single concise UPGRADE_READ…
Copilot Oct 10, 2025
0dd1418
REadme update
Oct 10, 2025
779e38f
Delete migrate-akka-to-pekko.sh
sntiwari1 Oct 10, 2025
683631f
Upgrade to Play Framework 3.0.5 and Apache Pekko 1.0.2
sntiwari1 Oct 10, 2025
810e8be
Update Apache Pekko version in upgrade documentation
sntiwari1 Oct 10, 2025
4ded3ad
Revise UPGRADE_README.md to remove changes section
sntiwari1 Oct 10, 2025
1acc223
updated secret
Rakshitha-D Oct 16, 2025
d1b6cdb
updated netty version
Rakshitha-D Oct 16, 2025
9f2d0e1
updated slf4j version
Rakshitha-D Oct 21, 2025
226f621
Refactor CertAddRequestValidator to improve null and type checks for …
Rakshitha-D Oct 21, 2025
d8e31ea
Enhance CertAddRequestValidator to support Scala Map conversion and i…
Rakshitha-D Oct 21, 2025
06a8e32
Refactor CertsServiceImpl to handle Scala Map conversion for related …
Rakshitha-D Oct 21, 2025
f2963bb
Refactor CertsServiceImpl to convert Scala Map to Java Map for reques…
Rakshitha-D Oct 21, 2025
31a9a58
reverted slf4j version
Rakshitha-D Oct 22, 2025
1a36398
removed comments
Rakshitha-D Oct 22, 2025
ba18f02
handled null pointer exception
Rakshitha-D Oct 22, 2025
dca783d
update null pointer exception handling
Rakshitha-D Oct 22, 2025
8379e28
Merge pull request #2 from Rakshitha-D/release-8.0.0
sntiwari1 Oct 23, 2025
07901c2
Update service/conf/application.conf
sntiwari1 Nov 4, 2025
55de32b
Added null check
Rakshitha-D Nov 4, 2025
494ed7c
Merge pull request #3 from Rakshitha-D/release-8.0.0
sntiwari1 Nov 4, 2025
159f95a
Merge pull request #113 from SNT01/release-8.0.0
pallakartheekreddy Nov 7, 2025
77040de
updated exception handling
Rakshitha-D Nov 7, 2025
623a7ac
Merge pull request #114 from Rakshitha-D/release-8.0.0
sntiwari1 Nov 7, 2025
ebedf0a
fix: Directly serializing the request object instead of converting it…
aimansharief Dec 16, 2025
b0a1555
fix : Handle 'total' as int or map in ESResponseMapper
aimansharief Dec 16, 2025
29a707c
fix: Add jackson-module-scala dependency
aimansharief Dec 16, 2025
18f1101
fix: Upgrade elasticsearch version to 7.10.2
aimansharief Dec 16, 2025
546e8d5
Merge pull request #115 from aimansharief/cert-reg-search-fix
pallakartheekreddy Dec 16, 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
74 changes: 74 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
name: Build and Deploy

on:
push:
tags:
- '*'

jobs:
ghcr-build-and-deploy:
runs-on: ubuntu-latest

permissions:
contents: read
packages: write

env:
REGISTRY: ghcr.io

steps:
- name: Checkout code
uses: actions/checkout@v2
with:
fetch-depth: 0

- name: Set up JDK 11
uses: actions/setup-java@v2
with:
distribution: 'temurin'
java-version: '11'

- name: Cache Maven packages
uses: actions/cache@v3
with:
path: |
~/.m2/repository
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
restore-keys: |
${{ runner.os }}-maven-
- name: Build
run: mvn clean install -DskipTests

- name: Package build artifact (Play dist)
run: mvn -f service/pom.xml play2:dist

- name: Upload artifact
uses: actions/upload-artifact@v4.3.1
with:
name: cert-service-dist
path: |
service/target/service-*-dist.zip
- name: Extract image tag details
id: image_vars
run: |
REPO_LOWER=$(echo "${GITHUB_REPOSITORY}" | tr '[:upper:]' '[:lower:]')
SHORT_SHA=$(git rev-parse --short HEAD)
TAG_LOWER=$(echo "${GITHUB_REF_NAME}" | tr '[:upper:]' '[:lower:]')
IMAGE_NAME=${{ env.REGISTRY }}/${REPO_LOWER}
IMAGE_TAG=${TAG_LOWER}_${SHORT_SHA}_${GITHUB_RUN_NUMBER}
echo "IMAGE_NAME=${IMAGE_NAME}" >> $GITHUB_ENV
echo "IMAGE_TAG=${IMAGE_TAG}" >> $GITHUB_ENV
- name: Log in to GitHub Container Registry (GHCR)
uses: docker/login-action@v2
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Build and push Docker image to GHCR
uses: docker/build-push-action@v4
with:
context: ./service/target
file: ./Dockerfile
push: true
tags: ${{ env.IMAGE_NAME }}:${{ env.IMAGE_TAG }}
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,4 @@ RUNNING_PID
all-actors/all-actors.iml
play-seed-wo-router.iml
sb-actor/sb-actor.iml
sb-utils/sb-utils.iml
sb-utils/sb-utils.iml*.tar.gz
6 changes: 3 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
FROM sunbird/openjdk-java11-alpine:latest
RUN apk update \
&& apk add unzip \
&& apk add curl \
&& apk upgrade \
&& apk add --no-cache unzip curl \
&& adduser -u 1001 -h /home/sunbird/ -D sunbird \
&& mkdir -p /home/sunbird/
ADD ./service-1.0.0-SNAPSHOT-dist.zip /home/sunbird/
Expand All @@ -10,4 +10,4 @@ RUN chown -R sunbird:sunbird /home/sunbird
USER sunbird
EXPOSE 9000
WORKDIR /home/sunbird/
CMD java -XX:+PrintFlagsFinal $JAVA_OPTIONS -cp '/home/sunbird/service-1.0.0-SNAPSHOT/lib/*' play.core.server.ProdServerStart /home/sunbird/service-1.0.0-SNAPSHOT
CMD java -XX:+PrintFlagsFinal $JAVA_OPTIONS -cp '/home/sunbird/service-1.0.0-SNAPSHOT/lib/*' play.core.server.ProdServerStart /home/sunbird/service-1.0.0-SNAPSHOT
81 changes: 81 additions & 0 deletions UPGRADE_README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# Play Framework and Pekko Upgrade

## Summary

This repository has been upgraded from Play Framework 2.7.2 with Akka 2.5.22 to Play Framework 3.0.5 with Apache Pekko 1.0.3.

## Version Changes

### Before
- Play Framework: 2.7.2
- Akka: 2.5.22
- Scala: 2.11.12
- Java: 8 (target), 17 (runtime)
- Jackson: 2.9.10.4
- SLF4J: 1.6.1
- Logback: 1.0.7
- Netty: 4.1.44

### After
- Play Framework: 3.0.5
- Apache Pekko: 1.0.3
- Scala: 2.13.12
- Java: 11 (target), 17 (runtime)
- Jackson: 2.14.3
- SLF4J: 2.0.9
- Logback: 1.4.14
- Netty: 4.1.93

## Reason for Upgrade

1. License Compliance: Akka changed from Apache 2.0 to Business Source License 1.1 requiring commercial licenses. 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.

### Play 3.0 API Updates
- ActorStartModule: Changed from AkkaGuiceSupport to PekkoGuiceSupport
- RequestHandler: Updated FutureConverters for Scala 2.13
- OnRequestHandler: Removed deprecated Http.Context, using Http.Request
- Fixed artifact names for Play 3.0 compatibility

## Build

Build all modules:
```
mvn clean install -DskipTests
```

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

## Build Verification

All modules compile successfully:
- certification-service
- sb-utils
- Cassandra Utils
- sb-es-utils
- all-actors
- play-service

Dependency tree verified: No Akka dependencies, only Scala 2.13.12 present.


## 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

## Known Issues

If you encounter NoClassDefFoundError for scala.collection.GenMap, verify dependency tree to ensure no Scala 2.12 artifacts are present:
```
mvn dependency:tree
```

Add exclusions for any scala-library or scala-reflect with version 2.12 if needed.
53 changes: 47 additions & 6 deletions all-actors/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,54 @@
<version>1.0.0</version>
<dependencies>
<dependency>
<groupId>com.typesafe.akka</groupId>
<artifactId>akka-actor_${scala.major.version}</artifactId>
<version>${akka.x.version}</version>
<groupId>org.apache.pekko</groupId>
<artifactId>pekko-actor_${scala.major.version}</artifactId>
<version>${pekko.version}</version>
</dependency>
<dependency>
<groupId>org.sunbird</groupId>
<artifactId>sb-es-utils</artifactId>
<version>1.0-SNAPSHOT</version>
<exclusions>
<exclusion>
<groupId>org.scala-lang</groupId>
<artifactId>scala-library</artifactId>
</exclusion>
<exclusion>
<groupId>org.scala-lang</groupId>
<artifactId>scala-reflect</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.sunbird</groupId>
<artifactId>sb-utils</artifactId>
<version>1.0.0-SNAPSHOT</version>
<exclusions>
<exclusion>
<groupId>org.scala-lang</groupId>
<artifactId>scala-library</artifactId>
</exclusion>
<exclusion>
<groupId>org.scala-lang</groupId>
<artifactId>scala-reflect</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.sunbird</groupId>
<artifactId>cassandra-utils</artifactId>
<version>1.0-SNAPSHOT</version>
<exclusions>
<exclusion>
<groupId>org.scala-lang</groupId>
<artifactId>scala-library</artifactId>
</exclusion>
<exclusion>
<groupId>org.scala-lang</groupId>
<artifactId>scala-reflect</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.mashape.unirest</groupId>
Expand All @@ -41,13 +71,24 @@
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
<!-- Explicitly declare Scala 2.13 -->
<dependency>
<groupId>org.scala-lang</groupId>
<artifactId>scala-library</artifactId>
<version>${scala.version}</version>
</dependency>

<dependency>
<groupId>com.typesafe.akka</groupId>
<artifactId>akka-testkit_${scala.major.version}</artifactId>
<version>2.5.22</version>
<groupId>org.apache.pekko</groupId>
<artifactId>pekko-testkit_${scala.major.version}</artifactId>
<version>${pekko.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-scala_${scala.major.version}</artifactId>
<version>2.13.0</version>
</dependency>
</dependencies>
<build>
<plugins>
Expand Down
6 changes: 3 additions & 3 deletions all-actors/src/main/java/org/sunbird/BaseActor.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package org.sunbird;

import akka.actor.UntypedAbstractActor;
import akka.event.DiagnosticLoggingAdapter;
import akka.event.Logging;
import org.apache.pekko.actor.UntypedAbstractActor;
import org.apache.pekko.event.DiagnosticLoggingAdapter;
import org.apache.pekko.event.Logging;
import org.sunbird.message.IResponseMessage;
import org.sunbird.message.Localizer;
import org.sunbird.message.ResponseCode;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package org.sunbird.actor;

import akka.actor.ActorRef;
import org.apache.pekko.actor.ActorRef;
import com.fasterxml.jackson.core.JsonProcessingException;
import org.sunbird.BaseActor;
import org.sunbird.BaseException;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package org.sunbird.service;


import akka.actor.ActorRef;
import org.apache.pekko.actor.ActorRef;
import com.fasterxml.jackson.core.JsonProcessingException;
import org.sunbird.BaseException;
import org.sunbird.request.Request;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package org.sunbird.serviceimpl;

import akka.actor.ActorRef;
import org.apache.pekko.actor.ActorRef;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.module.scala.DefaultScalaModule;
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.JsonNode;
import org.apache.commons.collections.CollectionUtils;
Expand All @@ -27,6 +28,7 @@
import org.sunbird.service.ICertService;
import org.sunbird.utilities.CertificateUtil;
import org.sunbird.utilities.ESResponseMapper;
import scala.jdk.javaapi.CollectionConverters;

import java.io.IOException;
import java.net.URL;
Expand All @@ -48,6 +50,7 @@ public class CertsServiceImpl implements ICertService {
static Map<String, String> headerMap = new HashMap<>();
static {
headerMap.put("Content-Type", "application/json");
requestMapper.registerModule(new DefaultScalaModule());
}

@Override
Expand Down Expand Up @@ -126,15 +129,26 @@ private Response processRecord(Map<String, Object> certReqAddMap, String version
Map<String,Object>recordMap= requestMapper.convertValue(certificate,Map.class);
return CertificateUtil.insertRecord(recordMap, certBackgroundActorRef);
}
private Certificate getCertificate(Map<String, Object> certReqAddMap) {
private Certificate getCertificate(Map<String, Object> certReqAddMap) throws BaseException {
Object relatedObj = certReqAddMap.get(JsonKeys.RELATED);
if (relatedObj == null) {
throw new BaseException(IResponseMessage.INVALID_REQUESTED_DATA, MessageFormat.format(getLocalizedMessage(IResponseMessage.MISSING_MANDATORY_PARAMS,null), JsonKeys.RELATED), ResponseCode.CLIENT_ERROR.getCode());
}
Map<String, Object> relatedMap = null;
if (relatedObj instanceof scala.collection.Map) {
relatedMap = (Map<String, Object>) CollectionConverters.asJava((scala.collection.Map<?, ?>) relatedObj);
} else if (relatedObj instanceof Map) {
relatedMap = (Map<String, Object>) relatedObj;
}

Certificate certificate = new Certificate.Builder()
.setId((String) certReqAddMap.get(JsonKeys.ID))
.setData(getData(certReqAddMap))
.setRevoked(false)
.setAccessCode((String)certReqAddMap.get(JsonKeys.ACCESS_CODE))
.setJsonUrl((String)certReqAddMap.get(JsonKeys.JSON_URL))
.setRecipient(getCompositeReciepientObject(certReqAddMap))
.setRelated((Map)certReqAddMap.get(JsonKeys.RELATED))
.setRelated(relatedMap)
.setReason((String)certReqAddMap.get(JsonKeys.REASON))
.build();
logger.info("CertsServiceImpl:getCertificate:certificate object formed.");
Expand All @@ -149,8 +163,18 @@ private Recipient getCompositeReciepientObject(Map<String, Object> certAddReques
return recipient;
}

private Map<String, Object> getData(Map<String, Object> certAddRequestMap) {
return (Map) certAddRequestMap.get(JsonKeys.JSON_DATA);
private Map<String, Object> getData(Map<String, Object> certAddRequestMap) throws BaseException {
Object jsonDataObj = certAddRequestMap.get(JsonKeys.JSON_DATA);
if (jsonDataObj instanceof scala.collection.Map) {
return (Map<String, Object>) CollectionConverters.asJava((scala.collection.Map<?, ?>) jsonDataObj);
} else if (jsonDataObj instanceof Map) {
return (Map<String, Object>) jsonDataObj;
}
throw new BaseException(
IResponseMessage.INVALID_REQUESTED_DATA,
"Invalid type for JSON_DATA: expected Scala Map or Java Map, but got "
+ (jsonDataObj == null ? "null" : jsonDataObj.getClass().getName()),
ResponseCode.CLIENT_ERROR.getCode());
}

@Override
Expand Down Expand Up @@ -505,16 +529,16 @@ public Response searchV2(Request request) throws BaseException{
private ESResponseMapper searchEsPostCall(Request request) throws BaseException {
ESResponseMapper mappedResponse = null;
try {
String requestBody = requestMapper.writeValueAsString(request.getRequest());
logger.info("CertsServiceImpl:search:request body found.");
Object requestObj = request.getRequest();
String requestBody = requestMapper.writeValueAsString(requestObj);
String apiToCall = CertVars.getEsSearchUri();
logger.info("CertsServiceImpl:search:complete url found: " + apiToCall);
Future<HttpResponse<JsonNode>> responseFuture = CertificateUtil.makeAsyncPostCall(apiToCall, requestBody, headerMap);
HttpResponse<JsonNode> jsonResponse = responseFuture.get();
if (jsonResponse != null && jsonResponse.getStatus() == HttpStatus.SC_OK) {
String jsonArray = jsonResponse.getBody().getObject().getJSONObject(JsonKeys.HITS).toString();
Map<String, Object> apiResp = requestMapper.readValue(jsonArray, Map.class);
mappedResponse = new ObjectMapper().convertValue(apiResp, ESResponseMapper.class);
mappedResponse = requestMapper.convertValue(apiResp, ESResponseMapper.class);
} else {
logger.error("CertsServiceImpl:searchEsPostCall: Invalid request data ");
throw new BaseException(IResponseMessage.INVALID_REQUESTED_DATA, jsonResponse.getBody().toString(), ResponseCode.CLIENT_ERROR.getCode());
Expand Down
Loading