Skip to content

Commit 4cc8ee3

Browse files
author
p250109
committed
notification controller and swagger added
1 parent 72abe0e commit 4cc8ee3

13 files changed

Lines changed: 283 additions & 2 deletions

File tree

api-gateway/src/main/resources/application.yml

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,14 @@ spring:
3737
- StripPrefix=2
3838
- name: AuthenticationFilter
3939

40+
- id: notification-service
41+
uri: ${NOTIFICATION_SERVICE_URI:lb://NOTIFICATION-SERVICE}
42+
predicates:
43+
- Path=/api/v1/notifications/**
44+
filters:
45+
- StripPrefix=2
46+
- name: AuthenticationFilter
47+
4048
springdoc:
4149
enable-native-support: true
4250
api-docs:
@@ -60,4 +68,7 @@ springdoc:
6068
primaryName: Connection Service
6169
- url: /api/v1/uploads/v3/api-docs
6270
name: Uploader Service
63-
primaryName: Uploader Service
71+
primaryName: Uploader Service
72+
- url: /api/v1/notifications/v3/api-docs
73+
name: Notification Service
74+
primaryName: Notification Service

docker-compose-new.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,8 @@ services:
196196
- linkedin-db
197197
- kafka
198198
- config-server
199+
ports:
200+
- "9293:9293"
199201
volumes:
200202
- ./logs/notification-service:/logs/notification-service
201203
logging:

notification-service/pom.xml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,22 @@
3131
<spring-cloud.version>2023.0.3</spring-cloud.version>
3232
</properties>
3333
<dependencies>
34+
<dependency>
35+
<groupId>org.springdoc</groupId>
36+
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
37+
<version>2.5.0</version>
38+
</dependency>
39+
<dependency>
40+
<groupId>io.swagger.core.v3</groupId>
41+
<artifactId>swagger-models-jakarta</artifactId>
42+
<version>2.2.29</version>
43+
<scope>compile</scope>
44+
</dependency>
45+
<dependency>
46+
<groupId>org.modelmapper</groupId>
47+
<artifactId>modelmapper</artifactId>
48+
<version>3.2.0</version>
49+
</dependency>
3450
<dependency>
3551
<groupId>org.springframework.boot</groupId>
3652
<artifactId>spring-boot-starter-data-jpa</artifactId>
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package com.premtsd.linkedin.notificationservice.configs;
2+
3+
import org.modelmapper.ModelMapper;
4+
import org.springframework.context.annotation.Bean;
5+
import org.springframework.context.annotation.Configuration;
6+
7+
@Configuration
8+
public class ModelMapperConfig {
9+
10+
@Bean
11+
public ModelMapper modelMapper() {
12+
return new ModelMapper();
13+
}
14+
}

notification-service/src/main/java/com/premtsd/linkedin/notificationservice/configs/appConfig.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,41 @@
55
import io.micrometer.core.instrument.MeterRegistry;
66
import org.springframework.context.annotation.Bean;
77
import org.springframework.context.annotation.Configuration;
8+
import io.swagger.v3.oas.models.Components;
9+
import io.swagger.v3.oas.models.OpenAPI;
10+
import io.swagger.v3.oas.models.info.Info;
11+
import io.swagger.v3.oas.models.security.SecurityRequirement;
12+
import io.swagger.v3.oas.models.security.SecurityScheme;
13+
import io.swagger.v3.oas.models.servers.Server;
14+
15+
import java.util.List;
816

917
@Configuration
1018
public class appConfig {
1119
@Bean
1220
public Capability capability(final MeterRegistry registry) {
1321
return new MicrometerCapability(registry);
1422
}
23+
24+
25+
@Bean
26+
public OpenAPI customOpenAPI() {
27+
final String securitySchemeName = "bearerAuth";
28+
29+
return new OpenAPI()
30+
.info(new Info()
31+
.title("Notification Service API")
32+
.version("1.0")
33+
.description("API for managing notifications"))
34+
.servers(List.of(new Server().url("http://localhost:8080/api/v1/notifications")))
35+
.addSecurityItem(new SecurityRequirement().addList(securitySchemeName))
36+
.components(new Components()
37+
.addSecuritySchemes(securitySchemeName,
38+
new SecurityScheme()
39+
.name(securitySchemeName)
40+
.type(SecurityScheme.Type.HTTP)
41+
.scheme("bearer")
42+
.bearerFormat("JWT"))); // Optional but recommended
43+
}
44+
1545
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package com.premtsd.linkedin.notificationservice.controller;
2+
3+
import com.premtsd.linkedin.notificationservice.auth.UserContextHolder;
4+
import com.premtsd.linkedin.notificationservice.dto.NotificationDto;
5+
import com.premtsd.linkedin.notificationservice.service.NotificationService;
6+
import lombok.RequiredArgsConstructor;
7+
import lombok.extern.slf4j.Slf4j;
8+
import org.springframework.http.ResponseEntity;
9+
import org.springframework.web.bind.annotation.*;
10+
11+
import java.util.List;
12+
13+
@RestController
14+
@RequestMapping("/notifications")
15+
@RequiredArgsConstructor
16+
@Slf4j
17+
public class NotificationController {
18+
19+
private final NotificationService notificationService;
20+
21+
/**
22+
* List all notifications for the authenticated user
23+
*/
24+
@GetMapping
25+
public ResponseEntity<List<NotificationDto>> getAllNotifications() {
26+
Long userId = UserContextHolder.getCurrentUserId();
27+
log.info("GET /notifications - Fetching all notifications for user: {}", userId);
28+
List<NotificationDto> notifications = notificationService.getAllNotifications(userId);
29+
log.info("Returning {} notifications for user: {}", notifications.size(), userId);
30+
return ResponseEntity.ok(notifications);
31+
}
32+
33+
/**
34+
* List only unread notifications for the authenticated user
35+
*/
36+
@GetMapping("/unread")
37+
public ResponseEntity<List<NotificationDto>> getUnreadNotifications() {
38+
Long userId = UserContextHolder.getCurrentUserId();
39+
log.info("GET /notifications/unread - Fetching unread notifications for user: {}", userId);
40+
List<NotificationDto> notifications = notificationService.getUnreadNotifications(userId);
41+
log.info("Returning {} unread notifications for user: {}", notifications.size(), userId);
42+
return ResponseEntity.ok(notifications);
43+
}
44+
45+
/**
46+
* Mark a specific notification as read
47+
*/
48+
@PutMapping("/{notificationId}/read")
49+
public ResponseEntity<NotificationDto> markNotificationAsRead(
50+
@PathVariable Long notificationId) {
51+
Long userId = UserContextHolder.getCurrentUserId();
52+
log.info("PUT /notifications/{}/read - Marking notification as read for user: {}", notificationId, userId);
53+
NotificationDto notification = notificationService.markAsRead(notificationId, userId);
54+
log.info("Notification {} marked as read successfully for user: {}", notificationId, userId);
55+
return ResponseEntity.ok(notification);
56+
}
57+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package com.premtsd.linkedin.notificationservice.dto;
2+
3+
import lombok.Data;
4+
5+
import java.time.LocalDateTime;
6+
7+
@Data
8+
public class NotificationDto {
9+
private Long id;
10+
private Long userId;
11+
private String message;
12+
private Boolean isRead;
13+
private LocalDateTime createdAt;
14+
}

notification-service/src/main/java/com/premtsd/linkedin/notificationservice/entity/Notification.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ public class Notification {
2020
private Long id;
2121
private Long userId;
2222
private String message;
23+
private Boolean isRead = false;
2324

2425
@CreationTimestamp
2526
private LocalDateTime createdAt;
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package com.premtsd.linkedin.notificationservice.exception;
2+
3+
import lombok.extern.slf4j.Slf4j;
4+
import org.springframework.http.HttpStatus;
5+
import org.springframework.http.ResponseEntity;
6+
import org.springframework.web.bind.annotation.ExceptionHandler;
7+
import org.springframework.web.bind.annotation.RestControllerAdvice;
8+
9+
import java.time.LocalDateTime;
10+
import java.util.HashMap;
11+
import java.util.Map;
12+
13+
@RestControllerAdvice
14+
@Slf4j
15+
public class GlobalExceptionHandler {
16+
17+
@ExceptionHandler(ResourceNotFoundException.class)
18+
public ResponseEntity<Map<String, Object>> handleResourceNotFoundException(ResourceNotFoundException ex) {
19+
log.error("Resource not found: {}", ex.getMessage());
20+
21+
Map<String, Object> errorResponse = new HashMap<>();
22+
errorResponse.put("timestamp", LocalDateTime.now());
23+
errorResponse.put("status", HttpStatus.NOT_FOUND.value());
24+
errorResponse.put("error", "Not Found");
25+
errorResponse.put("message", ex.getMessage());
26+
27+
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(errorResponse);
28+
}
29+
30+
@ExceptionHandler(Exception.class)
31+
public ResponseEntity<Map<String, Object>> handleGenericException(Exception ex) {
32+
log.error("Unexpected error occurred: {}", ex.getMessage(), ex);
33+
34+
Map<String, Object> errorResponse = new HashMap<>();
35+
errorResponse.put("timestamp", LocalDateTime.now());
36+
errorResponse.put("status", HttpStatus.INTERNAL_SERVER_ERROR.value());
37+
errorResponse.put("error", "Internal Server Error");
38+
errorResponse.put("message", "An unexpected error occurred");
39+
40+
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(errorResponse);
41+
}
42+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package com.premtsd.linkedin.notificationservice.exception;
2+
3+
public class ResourceNotFoundException extends RuntimeException {
4+
public ResourceNotFoundException(String message) {
5+
super(message);
6+
}
7+
}

0 commit comments

Comments
 (0)