diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/service/api/NotificationManagementService.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/service/api/NotificationManagementService.java index c86153ecc3..acc90ce506 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/service/api/NotificationManagementService.java +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/service/api/NotificationManagementService.java @@ -29,6 +29,10 @@ import javax.validation.constraints.Size; import javax.ws.rs.*; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; +import javax.ws.rs.core.StreamingOutput; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.charset.StandardCharsets; /** * Notifications related REST-API. @@ -64,6 +68,13 @@ import javax.ws.rs.core.Response; key = "dm:notif:mark-checked", roles = {"Internal/devicemgt-user"}, permissions = {"/device-mgt/notifications/update"} + ), + @Scope( + name = "Streaming Device Notifications", + description = "Real-time streaming of device notifications", + key = "dm:notifications:stream", + roles = {"Internal/devicemgt-user"}, + permissions = {"/device-mgt/notifications/stream"} ) } ) @@ -226,4 +237,48 @@ public interface NotificationManagementService { } ) Response clearAllNotifications(); + + /** + * SSE endpoint to send real-time notifications to the client. + * @return StreamingOutput for SSE response. + */ + @GET + @Path("/stream") + @Produces("text/event-stream") + @ApiOperation( + value = "Stream Real-Time Notifications", + notes = "Streams real-time notifications to the client via Server-Sent Events.", + response = StreamingOutput.class, + extensions = { + @Extension(properties = { + @ExtensionProperty(name = "scope", value = "dm:notifications:stream") + }) + } + ) + default Response streamNotifications() { + StreamingOutput streamingOutput = new StreamingOutput() { + public void write(OutputStream output) throws IOException { + String notification = "data: {\"message\": \"New Notification\"}\n\n"; + while (true) { + try { + System.out.println("Sending the notification: " + notification); + output.write(notification.getBytes(StandardCharsets.UTF_8)); + output.flush(); + + Thread.sleep(5000); + } catch (InterruptedException e) { + break; + } + } + } + }; + + return Response.ok(streamingOutput) + .header("Cache-Control", "no-cache") + .header("Connection", "keep-alive") + .header("Content-Type", "text/event-stream;charset=UTF-8") + .header("Access-Control-Allow-Origin", "*") + .build(); + } } + diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/webapp/WEB-INF/web.xml b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/webapp/WEB-INF/web.xml index d812c44d03..7319ecadaf 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/webapp/WEB-INF/web.xml +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/webapp/WEB-INF/web.xml @@ -52,6 +52,7 @@ /api/device-mgt/v1.0/whitelabel/.*/favicon, /api/device-mgt/v1.0/whitelabel/.*/logo, /api/device-mgt/v1.0/whitelabel/.*/icon, + /api/device-mgt/v1.0/notifications/stream diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.common/pom.xml b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.common/pom.xml index 3e9d8f7b0d..74909fd86a 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.common/pom.xml +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.common/pom.xml @@ -129,6 +129,37 @@ org.wso2.orbit.javax.xml.bind jaxb-api + + org.springframework + spring-web + + + org.springframework + spring-web + + + org.springframework + spring-context + 4.3.24.RELEASE + compile + + + org.springframework + spring-context + 4.3.24.RELEASE + compile + + + javax.ws.rs + javax.ws.rs-api + + + org.glassfish.hk2.external + javax.inject + 2.2.0-b21 + compile + + diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.common/src/main/java/io/entgra/device/mgt/core/device/mgt/common/notification/mgt/NotificationWorker.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.common/src/main/java/io/entgra/device/mgt/core/device/mgt/common/notification/mgt/NotificationWorker.java deleted file mode 100644 index 4711190df4..0000000000 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.common/src/main/java/io/entgra/device/mgt/core/device/mgt/common/notification/mgt/NotificationWorker.java +++ /dev/null @@ -1,49 +0,0 @@ -package io.entgra.device.mgt.core.device.mgt.common.notification.mgt; - -import java.util.concurrent.*; - -public class NotificationWorker { - private final BlockingQueue taskQueue; - private final ThreadPoolExecutor executor; - private boolean isInitialized = false; - - public NotificationWorker() { - this.taskQueue = new LinkedBlockingQueue<>(); - this.executor = new ThreadPoolExecutor(2, 4, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<>()); - } - - private synchronized void startWorker() { - if (!isInitialized) { - isInitialized = true; - System.out.println("Notification Service Worker Thread initialized."); - - executor.submit(() -> { - try { - while (true) { - Notification nextTask = taskQueue.take(); - System.out.println("New task added; processing in a separate thread."); - executor.submit(() -> processNotification(nextTask)); - } - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - System.out.println("Notification processing thread was interrupted, terminating."); - } - }); - } - } - - public synchronized void addNotificationTask(Notification notification) { - taskQueue.offer(notification); - startWorker(); - } - - private void processNotification(Notification notification) { - try { - System.out.println("Processing task: " + notification); - } catch (Exception e) { - System.err.println("Failed to process notification: " + notification + " due to " + e.getMessage()); - } - //The logic should be included in the service layer it will be moved in the relevant milestone --> SSE through notification service - } - -} diff --git a/features/device-mgt/io.entgra.device.mgt.core.device.mgt.basics.feature/src/main/resources/conf/mdm-ui-config.xml b/features/device-mgt/io.entgra.device.mgt.core.device.mgt.basics.feature/src/main/resources/conf/mdm-ui-config.xml index 45c3ebe581..07d8cb1a04 100644 --- a/features/device-mgt/io.entgra.device.mgt.core.device.mgt.basics.feature/src/main/resources/conf/mdm-ui-config.xml +++ b/features/device-mgt/io.entgra.device.mgt.core.device.mgt.basics.feature/src/main/resources/conf/mdm-ui-config.xml @@ -428,6 +428,7 @@ dm:admin:cea:sync am:pub:app:upload dm:devices:ops:status:update + dm:notifications:stream device-mgt