Loading src/main/java/org/etsi/osl/tmf/pcm620/api/ProductCatalogApiRouteBuilderEvents.java 0 → 100644 +114 −0 Original line number Diff line number Diff line /*- * ========================LICENSE_START================================= * org.etsi.osl.tmf.api * %% * Copyright (C) 2019 - 2020 openslice.io * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * =========================LICENSE_END================================== */ package org.etsi.osl.tmf.pcm620.api; import java.io.IOException; import java.util.HashMap; import java.util.Map; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.camel.ProducerTemplate; import org.apache.camel.builder.RouteBuilder; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.etsi.osl.centrallog.client.CLevel; import org.etsi.osl.centrallog.client.CentralLogger; import org.etsi.osl.tmf.common.model.Notification; import org.etsi.osl.tmf.pcm620.model.CatalogCreateNotification; import org.etsi.osl.tmf.pcm620.model.CatalogDeleteNotification; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; @Configuration @Component public class ProductCatalogApiRouteBuilderEvents extends RouteBuilder { private static final transient Log logger = LogFactory.getLog(ProductCatalogApiRouteBuilderEvents.class.getName()); @Value("${EVENT_PRODUCT_CATALOG_CREATE}") private String EVENT_CATALOG_CREATE = "direct:EVENT_CATALOG_CREATE"; @Value("${EVENT_PRODUCT_CATALOG_DELETE}") private String EVENT_CATALOG_DELETE = "direct:EVENT_CATALOG_DELETE"; @Value("${spring.application.name}") private String compname; @Autowired private ProducerTemplate template; @Autowired private CentralLogger centralLogger; @Override public void configure() throws Exception { // Configure routes for catalog events } /** * Publish notification events for catalog operations * @param n The notification to publish * @param objId The catalog object ID */ @Transactional public void publishEvent(final Notification n, final String objId) { n.setEventType(n.getClass().getName()); logger.info("will send Event for type " + n.getEventType()); try { String msgtopic = ""; if (n instanceof CatalogCreateNotification) { msgtopic = EVENT_CATALOG_CREATE; } else if (n instanceof CatalogDeleteNotification) { msgtopic = EVENT_CATALOG_DELETE; } Map<String, Object> map = new HashMap<>(); map.put("eventid", n.getEventId()); map.put("objId", objId); String apayload = toJsonString(n); template.sendBodyAndHeaders(msgtopic, apayload, map); centralLogger.log(CLevel.INFO, apayload, compname); } catch (Exception e) { e.printStackTrace(); logger.error("Cannot send Event . " + e.getMessage()); } } static String toJsonString(Object object) throws IOException { ObjectMapper mapper = new ObjectMapper(); mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); return mapper.writeValueAsString(object); } static <T> T toJsonObj(String content, Class<T> valueType) throws IOException { ObjectMapper mapper = new ObjectMapper(); mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); return mapper.readValue(content, valueType); } } No newline at end of file src/main/java/org/etsi/osl/tmf/pcm620/configuration/RestTemplateConfig.java 0 → 100644 +39 −0 Original line number Diff line number Diff line /*- * ========================LICENSE_START================================= * org.etsi.osl.tmf.api * %% * Copyright (C) 2019 - 2021 openslice.io * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * =========================LICENSE_END================================== */ package org.etsi.osl.tmf.pcm620.configuration; import java.time.Duration; import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestTemplate; @Configuration public class RestTemplateConfig { @Bean public RestTemplate restTemplate(RestTemplateBuilder builder) { return builder .setConnectTimeout(Duration.ofSeconds(10)) .setReadTimeout(Duration.ofSeconds(30)) .build(); } } No newline at end of file src/main/java/org/etsi/osl/tmf/pcm620/reposervices/CatalogCallbackService.java 0 → 100644 +158 −0 Original line number Diff line number Diff line /*- * ========================LICENSE_START================================= * org.etsi.osl.tmf.api * %% * Copyright (C) 2019 - 2021 openslice.io * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * =========================LICENSE_END================================== */ package org.etsi.osl.tmf.pcm620.reposervices; import java.util.List; import org.etsi.osl.tmf.pcm620.model.CatalogCreateEvent; import org.etsi.osl.tmf.pcm620.model.CatalogDeleteEvent; import org.etsi.osl.tmf.pcm620.model.EventSubscription; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; @Service public class CatalogCallbackService { private static final Logger logger = LoggerFactory.getLogger(CatalogCallbackService.class); @Autowired private EventSubscriptionRepoService eventSubscriptionRepoService; @Autowired private RestTemplate restTemplate; /** * Send catalog create event to all registered callback URLs * @param catalogCreateEvent The catalog create event to send */ public void sendCatalogCreateCallback(CatalogCreateEvent catalogCreateEvent) { List<EventSubscription> subscriptions = eventSubscriptionRepoService.findAll(); for (EventSubscription subscription : subscriptions) { if (shouldNotifySubscription(subscription, "catalogCreateEvent")) { sendCatalogCreateEventToCallback(subscription.getCallback(), catalogCreateEvent); } } } /** * Send catalog delete event to all registered callback URLs * @param catalogDeleteEvent The catalog delete event to send */ public void sendCatalogDeleteCallback(CatalogDeleteEvent catalogDeleteEvent) { List<EventSubscription> subscriptions = eventSubscriptionRepoService.findAll(); for (EventSubscription subscription : subscriptions) { if (shouldNotifySubscription(subscription, "catalogDeleteEvent")) { sendCatalogDeleteEventToCallback(subscription.getCallback(), catalogDeleteEvent); } } } /** * Send catalog create event to a specific callback URL * @param callbackUrl The callback URL to send to * @param event The catalog create event */ private void sendCatalogCreateEventToCallback(String callbackUrl, CatalogCreateEvent event) { try { String url = buildCallbackUrl(callbackUrl, "/listener/catalogCreateEvent"); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); HttpEntity<CatalogCreateEvent> entity = new HttpEntity<>(event, headers); ResponseEntity<String> response = restTemplate.exchange( url, HttpMethod.POST, entity, String.class); logger.info("Successfully sent catalog create event to callback URL: {} - Response: {}", url, response.getStatusCode()); } catch (Exception e) { logger.error("Failed to send catalog create event to callback URL: {}", callbackUrl, e); } } /** * Send catalog delete event to a specific callback URL * @param callbackUrl The callback URL to send to * @param event The catalog delete event */ private void sendCatalogDeleteEventToCallback(String callbackUrl, CatalogDeleteEvent event) { try { String url = buildCallbackUrl(callbackUrl, "/listener/catalogDeleteEvent"); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); HttpEntity<CatalogDeleteEvent> entity = new HttpEntity<>(event, headers); ResponseEntity<String> response = restTemplate.exchange( url, HttpMethod.POST, entity, String.class); logger.info("Successfully sent catalog delete event to callback URL: {} - Response: {}", url, response.getStatusCode()); } catch (Exception e) { logger.error("Failed to send catalog delete event to callback URL: {}", callbackUrl, e); } } /** * Build the full callback URL with the listener endpoint * @param baseUrl The base callback URL * @param listenerPath The listener path to append * @return The complete callback URL */ private String buildCallbackUrl(String baseUrl, String listenerPath) { if (baseUrl.endsWith("/")) { return baseUrl.substring(0, baseUrl.length() - 1) + listenerPath; } else { return baseUrl + listenerPath; } } /** * Check if a subscription should be notified for a specific event type * @param subscription The event subscription * @param eventType The event type to check * @return true if the subscription should be notified */ private boolean shouldNotifySubscription(EventSubscription subscription, String eventType) { // If no query is specified, notify all events if (subscription.getQuery() == null || subscription.getQuery().trim().isEmpty()) { return true; } // Check if the query contains the event type String query = subscription.getQuery().toLowerCase(); return query.contains("catalog") || query.contains(eventType.toLowerCase()) || query.contains("catalog.create") || query.contains("catalog.delete"); } } No newline at end of file src/main/java/org/etsi/osl/tmf/pcm620/reposervices/CatalogNotificationService.java 0 → 100644 +151 −0 Original line number Diff line number Diff line /*- * ========================LICENSE_START================================= * org.etsi.osl.tmf.api * %% * Copyright (C) 2019 - 2021 openslice.io * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * =========================LICENSE_END================================== */ package org.etsi.osl.tmf.pcm620.reposervices; import java.time.OffsetDateTime; import java.time.ZoneOffset; import java.util.UUID; import org.etsi.osl.tmf.pcm620.api.ProductCatalogApiRouteBuilderEvents; import org.etsi.osl.tmf.pcm620.model.Catalog; import org.etsi.osl.tmf.pcm620.model.CatalogCreateEvent; import org.etsi.osl.tmf.pcm620.model.CatalogCreateEventPayload; import org.etsi.osl.tmf.pcm620.model.CatalogCreateNotification; import org.etsi.osl.tmf.pcm620.model.CatalogDeleteEvent; import org.etsi.osl.tmf.pcm620.model.CatalogDeleteEventPayload; import org.etsi.osl.tmf.pcm620.model.CatalogDeleteNotification; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @Service @Transactional public class CatalogNotificationService { private static final Logger logger = LoggerFactory.getLogger(CatalogNotificationService.class); @Autowired private ProductCatalogApiRouteBuilderEvents eventPublisher; @Autowired private CatalogCallbackService catalogCallbackService; /** * Publish a catalog create notification * @param catalog The created catalog */ public void publishCatalogCreateNotification(Catalog catalog) { try { CatalogCreateNotification notification = createCatalogCreateNotification(catalog); eventPublisher.publishEvent(notification, catalog.getUuid()); // Send callbacks to registered subscribers catalogCallbackService.sendCatalogCreateCallback(notification.getEvent()); logger.info("Published catalog create notification for catalog ID: {}", catalog.getUuid()); } catch (Exception e) { logger.error("Error publishing catalog create notification for catalog ID: {}", catalog.getUuid(), e); } } /** * Publish a catalog delete notification * @param catalog The deleted catalog */ public void publishCatalogDeleteNotification(Catalog catalog) { try { CatalogDeleteNotification notification = createCatalogDeleteNotification(catalog); eventPublisher.publishEvent(notification, catalog.getUuid()); // Send callbacks to registered subscribers catalogCallbackService.sendCatalogDeleteCallback(notification.getEvent()); logger.info("Published catalog delete notification for catalog ID: {}", catalog.getUuid()); } catch (Exception e) { logger.error("Error publishing catalog delete notification for catalog ID: {}", catalog.getUuid(), e); } } /** * Create a catalog create notification * @param catalog The created catalog * @return CatalogCreateNotification */ private CatalogCreateNotification createCatalogCreateNotification(Catalog catalog) { CatalogCreateNotification notification = new CatalogCreateNotification(); // Set common notification properties notification.setEventId(UUID.randomUUID().toString()); notification.setEventTime(OffsetDateTime.now(ZoneOffset.UTC)); notification.setEventType(CatalogCreateNotification.class.getName()); notification.setResourcePath("/productCatalogManagement/v4/catalog/" + catalog.getUuid()); // Create event CatalogCreateEvent event = new CatalogCreateEvent(); event.setEventId(notification.getEventId()); event.setEventTime(notification.getEventTime()); event.setEventType("CatalogCreateEvent"); event.setTitle("Catalog Create Event"); event.setDescription("A catalog has been created"); event.setTimeOcurred(notification.getEventTime()); // Create event payload CatalogCreateEventPayload payload = new CatalogCreateEventPayload(); payload.setCatalog(catalog); event.setEvent(payload); notification.setEvent(event); return notification; } /** * Create a catalog delete notification * @param catalog The deleted catalog * @return CatalogDeleteNotification */ private CatalogDeleteNotification createCatalogDeleteNotification(Catalog catalog) { CatalogDeleteNotification notification = new CatalogDeleteNotification(); // Set common notification properties notification.setEventId(UUID.randomUUID().toString()); notification.setEventTime(OffsetDateTime.now(ZoneOffset.UTC)); notification.setEventType(CatalogDeleteNotification.class.getName()); notification.setResourcePath("/productCatalogManagement/v4/catalog/" + catalog.getUuid()); // Create event CatalogDeleteEvent event = new CatalogDeleteEvent(); event.setEventId(notification.getEventId()); event.setEventTime(notification.getEventTime()); event.setEventType("CatalogDeleteEvent"); event.setTitle("Catalog Delete Event"); event.setDescription("A catalog has been deleted"); event.setTimeOcurred(notification.getEventTime()); // Create event payload CatalogDeleteEventPayload payload = new CatalogDeleteEventPayload(); payload.setCatalog(catalog); event.setEvent(payload); notification.setEvent(event); return notification; } } No newline at end of file src/main/java/org/etsi/osl/tmf/pcm620/reposervices/EventSubscriptionRepoService.java +5 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ */ package org.etsi.osl.tmf.pcm620.reposervices; import java.util.List; import java.util.Optional; import java.util.UUID; Loading Loading @@ -62,4 +63,8 @@ public class EventSubscriptionRepoService { this.eventSubscriptionRepo.delete(optionalEventSubscription.get()); } } public List<EventSubscription> findAll() { return (List<EventSubscription>) this.eventSubscriptionRepo.findAll(); } } No newline at end of file Loading
src/main/java/org/etsi/osl/tmf/pcm620/api/ProductCatalogApiRouteBuilderEvents.java 0 → 100644 +114 −0 Original line number Diff line number Diff line /*- * ========================LICENSE_START================================= * org.etsi.osl.tmf.api * %% * Copyright (C) 2019 - 2020 openslice.io * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * =========================LICENSE_END================================== */ package org.etsi.osl.tmf.pcm620.api; import java.io.IOException; import java.util.HashMap; import java.util.Map; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.camel.ProducerTemplate; import org.apache.camel.builder.RouteBuilder; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.etsi.osl.centrallog.client.CLevel; import org.etsi.osl.centrallog.client.CentralLogger; import org.etsi.osl.tmf.common.model.Notification; import org.etsi.osl.tmf.pcm620.model.CatalogCreateNotification; import org.etsi.osl.tmf.pcm620.model.CatalogDeleteNotification; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; @Configuration @Component public class ProductCatalogApiRouteBuilderEvents extends RouteBuilder { private static final transient Log logger = LogFactory.getLog(ProductCatalogApiRouteBuilderEvents.class.getName()); @Value("${EVENT_PRODUCT_CATALOG_CREATE}") private String EVENT_CATALOG_CREATE = "direct:EVENT_CATALOG_CREATE"; @Value("${EVENT_PRODUCT_CATALOG_DELETE}") private String EVENT_CATALOG_DELETE = "direct:EVENT_CATALOG_DELETE"; @Value("${spring.application.name}") private String compname; @Autowired private ProducerTemplate template; @Autowired private CentralLogger centralLogger; @Override public void configure() throws Exception { // Configure routes for catalog events } /** * Publish notification events for catalog operations * @param n The notification to publish * @param objId The catalog object ID */ @Transactional public void publishEvent(final Notification n, final String objId) { n.setEventType(n.getClass().getName()); logger.info("will send Event for type " + n.getEventType()); try { String msgtopic = ""; if (n instanceof CatalogCreateNotification) { msgtopic = EVENT_CATALOG_CREATE; } else if (n instanceof CatalogDeleteNotification) { msgtopic = EVENT_CATALOG_DELETE; } Map<String, Object> map = new HashMap<>(); map.put("eventid", n.getEventId()); map.put("objId", objId); String apayload = toJsonString(n); template.sendBodyAndHeaders(msgtopic, apayload, map); centralLogger.log(CLevel.INFO, apayload, compname); } catch (Exception e) { e.printStackTrace(); logger.error("Cannot send Event . " + e.getMessage()); } } static String toJsonString(Object object) throws IOException { ObjectMapper mapper = new ObjectMapper(); mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); return mapper.writeValueAsString(object); } static <T> T toJsonObj(String content, Class<T> valueType) throws IOException { ObjectMapper mapper = new ObjectMapper(); mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); return mapper.readValue(content, valueType); } } No newline at end of file
src/main/java/org/etsi/osl/tmf/pcm620/configuration/RestTemplateConfig.java 0 → 100644 +39 −0 Original line number Diff line number Diff line /*- * ========================LICENSE_START================================= * org.etsi.osl.tmf.api * %% * Copyright (C) 2019 - 2021 openslice.io * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * =========================LICENSE_END================================== */ package org.etsi.osl.tmf.pcm620.configuration; import java.time.Duration; import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestTemplate; @Configuration public class RestTemplateConfig { @Bean public RestTemplate restTemplate(RestTemplateBuilder builder) { return builder .setConnectTimeout(Duration.ofSeconds(10)) .setReadTimeout(Duration.ofSeconds(30)) .build(); } } No newline at end of file
src/main/java/org/etsi/osl/tmf/pcm620/reposervices/CatalogCallbackService.java 0 → 100644 +158 −0 Original line number Diff line number Diff line /*- * ========================LICENSE_START================================= * org.etsi.osl.tmf.api * %% * Copyright (C) 2019 - 2021 openslice.io * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * =========================LICENSE_END================================== */ package org.etsi.osl.tmf.pcm620.reposervices; import java.util.List; import org.etsi.osl.tmf.pcm620.model.CatalogCreateEvent; import org.etsi.osl.tmf.pcm620.model.CatalogDeleteEvent; import org.etsi.osl.tmf.pcm620.model.EventSubscription; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; @Service public class CatalogCallbackService { private static final Logger logger = LoggerFactory.getLogger(CatalogCallbackService.class); @Autowired private EventSubscriptionRepoService eventSubscriptionRepoService; @Autowired private RestTemplate restTemplate; /** * Send catalog create event to all registered callback URLs * @param catalogCreateEvent The catalog create event to send */ public void sendCatalogCreateCallback(CatalogCreateEvent catalogCreateEvent) { List<EventSubscription> subscriptions = eventSubscriptionRepoService.findAll(); for (EventSubscription subscription : subscriptions) { if (shouldNotifySubscription(subscription, "catalogCreateEvent")) { sendCatalogCreateEventToCallback(subscription.getCallback(), catalogCreateEvent); } } } /** * Send catalog delete event to all registered callback URLs * @param catalogDeleteEvent The catalog delete event to send */ public void sendCatalogDeleteCallback(CatalogDeleteEvent catalogDeleteEvent) { List<EventSubscription> subscriptions = eventSubscriptionRepoService.findAll(); for (EventSubscription subscription : subscriptions) { if (shouldNotifySubscription(subscription, "catalogDeleteEvent")) { sendCatalogDeleteEventToCallback(subscription.getCallback(), catalogDeleteEvent); } } } /** * Send catalog create event to a specific callback URL * @param callbackUrl The callback URL to send to * @param event The catalog create event */ private void sendCatalogCreateEventToCallback(String callbackUrl, CatalogCreateEvent event) { try { String url = buildCallbackUrl(callbackUrl, "/listener/catalogCreateEvent"); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); HttpEntity<CatalogCreateEvent> entity = new HttpEntity<>(event, headers); ResponseEntity<String> response = restTemplate.exchange( url, HttpMethod.POST, entity, String.class); logger.info("Successfully sent catalog create event to callback URL: {} - Response: {}", url, response.getStatusCode()); } catch (Exception e) { logger.error("Failed to send catalog create event to callback URL: {}", callbackUrl, e); } } /** * Send catalog delete event to a specific callback URL * @param callbackUrl The callback URL to send to * @param event The catalog delete event */ private void sendCatalogDeleteEventToCallback(String callbackUrl, CatalogDeleteEvent event) { try { String url = buildCallbackUrl(callbackUrl, "/listener/catalogDeleteEvent"); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); HttpEntity<CatalogDeleteEvent> entity = new HttpEntity<>(event, headers); ResponseEntity<String> response = restTemplate.exchange( url, HttpMethod.POST, entity, String.class); logger.info("Successfully sent catalog delete event to callback URL: {} - Response: {}", url, response.getStatusCode()); } catch (Exception e) { logger.error("Failed to send catalog delete event to callback URL: {}", callbackUrl, e); } } /** * Build the full callback URL with the listener endpoint * @param baseUrl The base callback URL * @param listenerPath The listener path to append * @return The complete callback URL */ private String buildCallbackUrl(String baseUrl, String listenerPath) { if (baseUrl.endsWith("/")) { return baseUrl.substring(0, baseUrl.length() - 1) + listenerPath; } else { return baseUrl + listenerPath; } } /** * Check if a subscription should be notified for a specific event type * @param subscription The event subscription * @param eventType The event type to check * @return true if the subscription should be notified */ private boolean shouldNotifySubscription(EventSubscription subscription, String eventType) { // If no query is specified, notify all events if (subscription.getQuery() == null || subscription.getQuery().trim().isEmpty()) { return true; } // Check if the query contains the event type String query = subscription.getQuery().toLowerCase(); return query.contains("catalog") || query.contains(eventType.toLowerCase()) || query.contains("catalog.create") || query.contains("catalog.delete"); } } No newline at end of file
src/main/java/org/etsi/osl/tmf/pcm620/reposervices/CatalogNotificationService.java 0 → 100644 +151 −0 Original line number Diff line number Diff line /*- * ========================LICENSE_START================================= * org.etsi.osl.tmf.api * %% * Copyright (C) 2019 - 2021 openslice.io * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * =========================LICENSE_END================================== */ package org.etsi.osl.tmf.pcm620.reposervices; import java.time.OffsetDateTime; import java.time.ZoneOffset; import java.util.UUID; import org.etsi.osl.tmf.pcm620.api.ProductCatalogApiRouteBuilderEvents; import org.etsi.osl.tmf.pcm620.model.Catalog; import org.etsi.osl.tmf.pcm620.model.CatalogCreateEvent; import org.etsi.osl.tmf.pcm620.model.CatalogCreateEventPayload; import org.etsi.osl.tmf.pcm620.model.CatalogCreateNotification; import org.etsi.osl.tmf.pcm620.model.CatalogDeleteEvent; import org.etsi.osl.tmf.pcm620.model.CatalogDeleteEventPayload; import org.etsi.osl.tmf.pcm620.model.CatalogDeleteNotification; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @Service @Transactional public class CatalogNotificationService { private static final Logger logger = LoggerFactory.getLogger(CatalogNotificationService.class); @Autowired private ProductCatalogApiRouteBuilderEvents eventPublisher; @Autowired private CatalogCallbackService catalogCallbackService; /** * Publish a catalog create notification * @param catalog The created catalog */ public void publishCatalogCreateNotification(Catalog catalog) { try { CatalogCreateNotification notification = createCatalogCreateNotification(catalog); eventPublisher.publishEvent(notification, catalog.getUuid()); // Send callbacks to registered subscribers catalogCallbackService.sendCatalogCreateCallback(notification.getEvent()); logger.info("Published catalog create notification for catalog ID: {}", catalog.getUuid()); } catch (Exception e) { logger.error("Error publishing catalog create notification for catalog ID: {}", catalog.getUuid(), e); } } /** * Publish a catalog delete notification * @param catalog The deleted catalog */ public void publishCatalogDeleteNotification(Catalog catalog) { try { CatalogDeleteNotification notification = createCatalogDeleteNotification(catalog); eventPublisher.publishEvent(notification, catalog.getUuid()); // Send callbacks to registered subscribers catalogCallbackService.sendCatalogDeleteCallback(notification.getEvent()); logger.info("Published catalog delete notification for catalog ID: {}", catalog.getUuid()); } catch (Exception e) { logger.error("Error publishing catalog delete notification for catalog ID: {}", catalog.getUuid(), e); } } /** * Create a catalog create notification * @param catalog The created catalog * @return CatalogCreateNotification */ private CatalogCreateNotification createCatalogCreateNotification(Catalog catalog) { CatalogCreateNotification notification = new CatalogCreateNotification(); // Set common notification properties notification.setEventId(UUID.randomUUID().toString()); notification.setEventTime(OffsetDateTime.now(ZoneOffset.UTC)); notification.setEventType(CatalogCreateNotification.class.getName()); notification.setResourcePath("/productCatalogManagement/v4/catalog/" + catalog.getUuid()); // Create event CatalogCreateEvent event = new CatalogCreateEvent(); event.setEventId(notification.getEventId()); event.setEventTime(notification.getEventTime()); event.setEventType("CatalogCreateEvent"); event.setTitle("Catalog Create Event"); event.setDescription("A catalog has been created"); event.setTimeOcurred(notification.getEventTime()); // Create event payload CatalogCreateEventPayload payload = new CatalogCreateEventPayload(); payload.setCatalog(catalog); event.setEvent(payload); notification.setEvent(event); return notification; } /** * Create a catalog delete notification * @param catalog The deleted catalog * @return CatalogDeleteNotification */ private CatalogDeleteNotification createCatalogDeleteNotification(Catalog catalog) { CatalogDeleteNotification notification = new CatalogDeleteNotification(); // Set common notification properties notification.setEventId(UUID.randomUUID().toString()); notification.setEventTime(OffsetDateTime.now(ZoneOffset.UTC)); notification.setEventType(CatalogDeleteNotification.class.getName()); notification.setResourcePath("/productCatalogManagement/v4/catalog/" + catalog.getUuid()); // Create event CatalogDeleteEvent event = new CatalogDeleteEvent(); event.setEventId(notification.getEventId()); event.setEventTime(notification.getEventTime()); event.setEventType("CatalogDeleteEvent"); event.setTitle("Catalog Delete Event"); event.setDescription("A catalog has been deleted"); event.setTimeOcurred(notification.getEventTime()); // Create event payload CatalogDeleteEventPayload payload = new CatalogDeleteEventPayload(); payload.setCatalog(catalog); event.setEvent(payload); notification.setEvent(event); return notification; } } No newline at end of file
src/main/java/org/etsi/osl/tmf/pcm620/reposervices/EventSubscriptionRepoService.java +5 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ */ package org.etsi.osl.tmf.pcm620.reposervices; import java.util.List; import java.util.Optional; import java.util.UUID; Loading Loading @@ -62,4 +63,8 @@ public class EventSubscriptionRepoService { this.eventSubscriptionRepo.delete(optionalEventSubscription.get()); } } public List<EventSubscription> findAll() { return (List<EventSubscription>) this.eventSubscriptionRepo.findAll(); } } No newline at end of file