From aea48e986c482dd2a29ab10da0a45426d6d48d68 Mon Sep 17 00:00:00 2001 From: "sunil.n" Date: Mon, 3 Nov 2025 12:14:19 +0530 Subject: [PATCH] Implement scheduler function to send FileReadyNotifications to all subscribers every 15 mins Change-Id: I1e363a020bea383a2ad269e8a042ea8c478eb8a3 Signed-off-by: sunil.n --- .../rapp-ran-nssmf-simulator/README.md | 177 ++++++++++++++++++++- .../controller/FileDataReportingMnSController.java | 29 ++++ .../ran/nssmf/simulator/dto/DateTimeDTO.java | 23 +++ .../ran/nssmf/simulator/dto/FileInfoDTO.java | 36 +++++ .../nssmf/simulator/dto/NotificationHeaderDTO.java | 24 +++ .../nssmf/simulator/dto/NotifyFileReadyDTO.java | 26 +++ 6 files changed, 311 insertions(+), 4 deletions(-) create mode 100644 sample-rapp-generator/rapp-ran-nssmf-simulator/ran-nssmf-simulator/src/main/java/org/oransc/ran/nssmf/simulator/dto/DateTimeDTO.java create mode 100644 sample-rapp-generator/rapp-ran-nssmf-simulator/ran-nssmf-simulator/src/main/java/org/oransc/ran/nssmf/simulator/dto/FileInfoDTO.java create mode 100644 sample-rapp-generator/rapp-ran-nssmf-simulator/ran-nssmf-simulator/src/main/java/org/oransc/ran/nssmf/simulator/dto/NotificationHeaderDTO.java create mode 100644 sample-rapp-generator/rapp-ran-nssmf-simulator/ran-nssmf-simulator/src/main/java/org/oransc/ran/nssmf/simulator/dto/NotifyFileReadyDTO.java diff --git a/sample-rapp-generator/rapp-ran-nssmf-simulator/README.md b/sample-rapp-generator/rapp-ran-nssmf-simulator/README.md index e9d7f2d..2ac5cbd 100644 --- a/sample-rapp-generator/rapp-ran-nssmf-simulator/README.md +++ b/sample-rapp-generator/rapp-ran-nssmf-simulator/README.md @@ -1,6 +1,6 @@ 5G RAN NSSMF Simulator Rapp -5G RAN NSSMF Simulator Rapp implements 5G RAN NSSMF Interfaces for subscriptions, NSSI creation, modifiction, get and delete apis according to 3GPP 28.532 +5G RAN NSSMF Simulator Rapp implements 5G RAN NSSMF Interfaces for subscriptions, NSSI creation, modification, get and delete APIs according to 3GPP 28.532 ## API Documentation @@ -40,6 +40,7 @@ - Stores subscription details in memory - Returns the subscription location in the `Location` header - Logs all subscription operations for debugging +- Sends automated file ready notifications every 5 minutes to all active subscribers #### Example Usage @@ -64,14 +65,182 @@ Content-Type: application/json } ``` +### File Ready Notification API + +#### Automated Notifications +The simulator automatically sends file ready notifications to all subscribed endpoints every 5 minutes. + +**Notification Endpoint**: The callback URL provided during subscription +**Method**: `POST` +**Content-Type**: `application/json` + +#### Notification Body Structure +```json +{ + "notificationHeader": { + "notificationId": "notif-1234567890", + "notificationType": "notifyFileReady", + "eventTime": { + "dateTime": "2025-01-03T12:09:48.123" + } + }, + "fileInfoList": [ + { + "fileLocation": "http://example.com/files/sample-performance-data-1234567890.csv", + "fileSize": 1024, + "fileReadyTime": { + "dateTime": "2025-01-03T12:09:48.123" + }, + "fileExpirationTime": { + "dateTime": "2025-01-04T12:09:48.123" + }, + "fileCompression": "gzip", + "fileFormat": "CSV", + "fileDataType": "Performance", + "jobId": "job-1234567890" + } + ], + "additionalText": "Sample file ready notification from NSSMF simulator" +} +``` + +#### Notification Fields Description + +**NotificationHeader:** +- `notificationId`: Unique identifier for the notification +- `notificationType`: Type of notification (always "notifyFileReady") +- `eventTime`: Timestamp when the notification was generated + +**FileInfo:** +- `fileLocation`: URL where the file can be accessed +- `fileSize`: Size of the file in bytes +- `fileReadyTime`: Timestamp when the file became available +- `fileExpirationTime`: Timestamp when the file will expire +- `fileCompression`: Compression format used (e.g., "gzip") +- `fileFormat`: File format (e.g., "CSV", "JSON") +- `fileDataType`: Type of data in the file (e.g., "Performance") +- `jobId`: Unique identifier for the job that generated the file + #### Implementation Details - **Subscription Storage**: In-memory HashMap (subscriptionMap) - **ID Generation**: Sequential integer starting from 1 - **3GPP Version**: v17.0.0 - **Server Port**: 8080 - **Logging**: Comprehensive logging for all operations +- **Notification Schedule**: Every 5 minutes (300,000 ms) +- **Data Models**: Complete DTO structure for 3GPP compliance + +## Data Transfer Objects (DTOs) + +### Core DTOs +- **SubscriptionRequestDTO**: Handles subscription requests with callback URI validation +- **SubscriptionDTO**: Response object for subscription confirmation +- **NotifyFileReadyDTO**: Complete notification payload sent to subscribers +- **NotificationHeaderDTO**: Standard 3GPP notification header with metadata +- **FileInfoDTO**: Detailed file information including location, size, and timestamps +- **DateTimeDTO**: Standardized date/time format using ISO 8601 + +### DTO Features +- **Lombok Integration**: Automatic getter/setter generation and builder patterns +- **Validation**: Jakarta validation annotations for request validation +- **Builder Pattern**: Fluent API for object creation +- **Sample Data**: Static factory methods for creating test data + +## Technical Architecture + +### Framework & Technology Stack +- **Spring Boot 3.5.5** with Java 21 +- **Gradle** build system +- **Lombok** for reducing boilerplate code +- **Jakarta Validation** for request validation +- **Spring Web** for REST API endpoints +- **Spring Scheduling** for periodic notification tasks + +### Key Components +- **FileDataReportingMnSController**: REST controller handling subscriptions and notifications +- **Scheduled Notifications**: Automated file ready notifications every 5 minutes +- **RestTemplate**: HTTP client for sending callback notifications +- **In-memory Storage**: HashMap-based subscription management + +## Directory Structure + +``` +src/ +├── main/ +│ ├── java/org/oransc/ran/nssmf/simulator/ +│ │ ├── controller/ +│ │ │ └── FileDataReportingMnSController.java +│ │ ├── dto/ +│ │ │ ├── DateTimeDTO.java +│ │ │ ├── FileInfoDTO.java +│ │ │ ├── NotificationHeaderDTO.java +│ │ │ ├── NotifyFileReadyDTO.java +│ │ │ ├── SubscriptionDTO.java +│ │ │ └── SubscriptionRequestDTO.java +│ │ └── RanNssmfSimulatorApplication.java +│ └── resources/ +│ └── application.properties +└── test/ + └── java/org/oransc/ran_nssmf_simulator/ +``` + +## Configuration + +### Application Properties +- `spring.application.name=ran-nssmf-simulator` +- `mns.fileDataReporting.version=v17.0.0` +- `server.port=8080` +- `spring.jackson.serialization.fail-on-empty-beans=false` + +### Build Configuration +- **Java Version**: 21 +- **Spring Boot Version**: 3.5.5 +- **Dependency Management**: Spring Boot Gradle Plugin +- **Testing**: JUnit 5 with Spring Boot Test + +## Deployment + +### Docker Support +- **Dockerfile**: Contains instructions to build a Docker image for the Rapp +- **Containerization**: Ready for deployment in containerized environments +- **Port Exposure**: 8080 for HTTP access + +### Running the Application + +**Using Gradle:** +```bash +./gradlew bootRun +``` + +**Using Java:** +```bash +./gradlew build +java -jar build/libs/ran-nssmf-simulator-0.0.1-SNAPSHOT.jar +``` + +**Using Docker:** +```bash +docker build -t ran-nssmf-simulator . +docker run -p 8080:8080 ran-nssmf-simulator +``` + +## Testing and Integration + +### Health Checks +- **Spring Boot Actuator**: Available for health monitoring +- **Endpoint**: `http://localhost:8080/actuator/health` + +### Logging +- **Comprehensive Logging**: All subscription and notification operations are logged +- **Debug Information**: Detailed logs for troubleshooting integration issues +- **Error Handling**: Graceful error handling for failed notifications -Directory Structure +## Use Cases -src - contains source code for the Rapp -Dockerfile - contains instructions to build a Docker image for the Rapp +This simulator is designed to: +1. **Test Integration**: Allow other RIC components to test NSSMF integration +2. **Development Support**: Provide a mock NSSMF for development without real network equipment +3. **Standard Compliance**: Demonstrate 3GPP 28.532 interface compliance +4. **Callback Testing**: Enable testing of asynchronous notification mechanisms +5. **Performance Testing**: Support load testing with multiple subscribers +6. **API Validation**: Validate client implementations against 3GPP standards diff --git a/sample-rapp-generator/rapp-ran-nssmf-simulator/ran-nssmf-simulator/src/main/java/org/oransc/ran/nssmf/simulator/controller/FileDataReportingMnSController.java b/sample-rapp-generator/rapp-ran-nssmf-simulator/ran-nssmf-simulator/src/main/java/org/oransc/ran/nssmf/simulator/controller/FileDataReportingMnSController.java index 273cdd0..b55d4cf 100644 --- a/sample-rapp-generator/rapp-ran-nssmf-simulator/ran-nssmf-simulator/src/main/java/org/oransc/ran/nssmf/simulator/controller/FileDataReportingMnSController.java +++ b/sample-rapp-generator/rapp-ran-nssmf-simulator/ran-nssmf-simulator/src/main/java/org/oransc/ran/nssmf/simulator/controller/FileDataReportingMnSController.java @@ -3,16 +3,19 @@ package org.oransc.ran.nssmf.simulator.controller; import jakarta.servlet.http.HttpServletRequest; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; +import org.oransc.ran.nssmf.simulator.dto.NotifyFileReadyDTO; import org.oransc.ran.nssmf.simulator.dto.SubscriptionDTO; import org.oransc.ran.nssmf.simulator.dto.SubscriptionRequestDTO; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.ResponseEntity; import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.client.RestTemplate; import java.net.URI; import java.util.HashMap; @@ -29,6 +32,9 @@ public class FileDataReportingMnSController { Map subscriptionMap = new HashMap<>(); static int subscriptionId = 0; + private final RestTemplate restTemplate; + + @PostMapping("/subscriptions") public ResponseEntity subscribe(HttpServletRequest httpRequest, @Valid @RequestBody SubscriptionRequestDTO request) throws Exception { @@ -49,4 +55,27 @@ public class FileDataReportingMnSController { return ResponseEntity.created(location).body(subscriptionDTO); } + + @Scheduled(fixedRate = 300000) // 15 minutes = 900,000 ms + public void sendFileReadyNotifications() { + logger.info("Starting to send file ready notifications to {} subscribers", subscriptionMap.size()); + + subscriptionMap.forEach((subscriptionId, subscription) -> { + try { + NotifyFileReadyDTO notification = NotifyFileReadyDTO.createSampleNotification(); + + ResponseEntity response = restTemplate.postForEntity( + subscription.getCallbackUri(), + notification, + String.class + ); + + logger.info("Successfully sent notification to subscription {} at {}. Response status: {}", subscriptionId, subscription.getCallbackUri(), response.getStatusCode()); + } catch (Exception e) { + logger.error("Failed to send notification to subscription {} at {}. Error: {}", subscriptionId, subscription.getCallbackUri(), e.getMessage()); + } + }); + + logger.info("Completed sending file ready notifications"); + } } diff --git a/sample-rapp-generator/rapp-ran-nssmf-simulator/ran-nssmf-simulator/src/main/java/org/oransc/ran/nssmf/simulator/dto/DateTimeDTO.java b/sample-rapp-generator/rapp-ran-nssmf-simulator/ran-nssmf-simulator/src/main/java/org/oransc/ran/nssmf/simulator/dto/DateTimeDTO.java new file mode 100644 index 0000000..158a92b --- /dev/null +++ b/sample-rapp-generator/rapp-ran-nssmf-simulator/ran-nssmf-simulator/src/main/java/org/oransc/ran/nssmf/simulator/dto/DateTimeDTO.java @@ -0,0 +1,23 @@ +package org.oransc.ran.nssmf.simulator.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; + +@NoArgsConstructor +@AllArgsConstructor +@Builder +@Data +public class DateTimeDTO { + private String dateTime; + + public static DateTimeDTO now() { + return DateTimeDTO.builder() + .dateTime(LocalDateTime.now().format(DateTimeFormatter.ISO_DATE_TIME)) + .build(); + } +} diff --git a/sample-rapp-generator/rapp-ran-nssmf-simulator/ran-nssmf-simulator/src/main/java/org/oransc/ran/nssmf/simulator/dto/FileInfoDTO.java b/sample-rapp-generator/rapp-ran-nssmf-simulator/ran-nssmf-simulator/src/main/java/org/oransc/ran/nssmf/simulator/dto/FileInfoDTO.java new file mode 100644 index 0000000..de1367c --- /dev/null +++ b/sample-rapp-generator/rapp-ran-nssmf-simulator/ran-nssmf-simulator/src/main/java/org/oransc/ran/nssmf/simulator/dto/FileInfoDTO.java @@ -0,0 +1,36 @@ +package org.oransc.ran.nssmf.simulator.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@NoArgsConstructor +@AllArgsConstructor +@Builder +@Data +public class FileInfoDTO { + private String fileLocation; + private Integer fileSize; + private DateTimeDTO fileReadyTime; + private DateTimeDTO fileExpirationTime; + private String fileCompression; + private String fileFormat; + private String fileDataType; + private String jobId; + + public static FileInfoDTO createSampleFileInfo() { + return FileInfoDTO.builder() + .fileLocation("http://example.com/files/sample-performance-data-" + System.currentTimeMillis() + ".csv") + .fileSize(1024) + .fileReadyTime(DateTimeDTO.now()) + .fileExpirationTime(DateTimeDTO.builder() + .dateTime(java.time.LocalDateTime.now().plusHours(24).format(java.time.format.DateTimeFormatter.ISO_DATE_TIME)) + .build()) + .fileCompression("gzip") + .fileFormat("CSV") + .fileDataType("Performance") + .jobId("job-" + System.currentTimeMillis()) + .build(); + } +} diff --git a/sample-rapp-generator/rapp-ran-nssmf-simulator/ran-nssmf-simulator/src/main/java/org/oransc/ran/nssmf/simulator/dto/NotificationHeaderDTO.java b/sample-rapp-generator/rapp-ran-nssmf-simulator/ran-nssmf-simulator/src/main/java/org/oransc/ran/nssmf/simulator/dto/NotificationHeaderDTO.java new file mode 100644 index 0000000..9523107 --- /dev/null +++ b/sample-rapp-generator/rapp-ran-nssmf-simulator/ran-nssmf-simulator/src/main/java/org/oransc/ran/nssmf/simulator/dto/NotificationHeaderDTO.java @@ -0,0 +1,24 @@ +package org.oransc.ran.nssmf.simulator.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@NoArgsConstructor +@AllArgsConstructor +@Builder +@Data +public class NotificationHeaderDTO { + private String notificationId; + private String notificationType; + private DateTimeDTO eventTime; + + public static NotificationHeaderDTO createFileReadyHeader() { + return NotificationHeaderDTO.builder() + .notificationId("notif-" + System.currentTimeMillis()) + .notificationType("notifyFileReady") + .eventTime(DateTimeDTO.now()) + .build(); + } +} diff --git a/sample-rapp-generator/rapp-ran-nssmf-simulator/ran-nssmf-simulator/src/main/java/org/oransc/ran/nssmf/simulator/dto/NotifyFileReadyDTO.java b/sample-rapp-generator/rapp-ran-nssmf-simulator/ran-nssmf-simulator/src/main/java/org/oransc/ran/nssmf/simulator/dto/NotifyFileReadyDTO.java new file mode 100644 index 0000000..2f0b262 --- /dev/null +++ b/sample-rapp-generator/rapp-ran-nssmf-simulator/ran-nssmf-simulator/src/main/java/org/oransc/ran/nssmf/simulator/dto/NotifyFileReadyDTO.java @@ -0,0 +1,26 @@ +package org.oransc.ran.nssmf.simulator.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +@NoArgsConstructor +@AllArgsConstructor +@Builder +@Data +public class NotifyFileReadyDTO { + private NotificationHeaderDTO notificationHeader; + private List fileInfoList; + private String additionalText; + + public static NotifyFileReadyDTO createSampleNotification() { + return NotifyFileReadyDTO.builder() + .notificationHeader(NotificationHeaderDTO.createFileReadyHeader()) + .fileInfoList(List.of(FileInfoDTO.createSampleFileInfo())) + .additionalText("Sample file ready notification from NSSMF simulator") + .build(); + } +} -- 2.16.6