diff --git a/reactive/src/main/java/com/example/reactive/BlogController.java b/reactive/src/main/java/com/example/reactive/BlogController.java index 482d9d2..8cbbc06 100644 --- a/reactive/src/main/java/com/example/reactive/BlogController.java +++ b/reactive/src/main/java/com/example/reactive/BlogController.java @@ -9,35 +9,76 @@ public class BlogController { private final BlogService blogService; + /**** + * Constructs a BlogController with the specified BlogService. + * + * @param blogService the service used to handle blog operations + */ public BlogController(BlogService blogService) { this.blogService = blogService; } + /** + * Creates a new blog entry. + * + * @param blog the blog data to create + * @return a Mono emitting the created blog + */ @PostMapping public Mono createBlog(@RequestBody Blog blog) { return blogService.createBlog(blog); } + /** + * Retrieves all blog entries as a reactive stream. + * + * @return a Flux emitting all Blog entities + */ @GetMapping public Flux getAllBlogs() { return blogService.getAllBlogs(); } + /** + * Retrieves a blog by its unique identifier. + * + * @param id the unique identifier of the blog to retrieve + * @return a Mono emitting the blog with the specified ID, or empty if not found + */ @GetMapping("/{id}") public Mono getBlogById(@PathVariable String id) { return blogService.getBlogById(id); } + /** + * Retrieves all blogs authored by the specified author as a reactive stream. + * + * @param author the name of the author whose blogs are to be retrieved + * @return a Flux emitting blogs written by the given author + */ @GetMapping("/author/{author}") public Flux getBlogsByAuthor(@PathVariable String author) { return blogService.getBlogsByAuthor(author); } + /** + * Updates an existing blog with the specified ID using the provided blog data. + * + * @param id the unique identifier of the blog to update + * @param blog the new blog data to apply + * @return a Mono emitting the updated blog + */ @PutMapping("/{id}") public Mono updateBlog(@PathVariable String id, @RequestBody Blog blog) { return blogService.updateBlog(id, blog); } + /** + * Deletes a blog with the specified ID. + * + * @param id the unique identifier of the blog to delete + * @return a Mono signaling completion when the blog is deleted + */ @DeleteMapping("/{id}") public Mono deleteBlog(@PathVariable String id) { return blogService.deleteBlog(id); diff --git a/reactive/src/main/java/com/example/reactive/BlogRepository.java b/reactive/src/main/java/com/example/reactive/BlogRepository.java index dc2553c..80117f5 100644 --- a/reactive/src/main/java/com/example/reactive/BlogRepository.java +++ b/reactive/src/main/java/com/example/reactive/BlogRepository.java @@ -4,5 +4,11 @@ import reactor.core.publisher.Flux; public interface BlogRepository extends ReactiveMongoRepository { - Flux findByAuthor(String author); + /**** + * Returns a reactive stream of blog entries authored by the specified user. + * + * @param author the author's name to filter blog entries by + * @return a Flux emitting all Blog entities with the given author + */ +Flux findByAuthor(String author); } diff --git a/reactive/src/main/java/com/example/reactive/BlogService.java b/reactive/src/main/java/com/example/reactive/BlogService.java index c49fd6c..0f847eb 100644 --- a/reactive/src/main/java/com/example/reactive/BlogService.java +++ b/reactive/src/main/java/com/example/reactive/BlogService.java @@ -8,26 +8,61 @@ public class BlogService { private final BlogRepository blogRepository; + /**** + * Constructs a BlogService with the specified BlogRepository for data access. + * + * @param blogRepository the repository used for blog persistence operations + */ public BlogService(BlogRepository blogRepository) { this.blogRepository = blogRepository; } + /** + * Creates a new blog entry and saves it to the repository. + * + * @param blog the blog entity to be created + * @return a Mono emitting the saved blog entity + */ public Mono createBlog(Blog blog) { return blogRepository.save(blog); } + /** + * Retrieves all blog entries as a reactive stream. + * + * @return a Flux emitting all Blog entities + */ public Flux getAllBlogs() { return blogRepository.findAll(); } + /** + * Retrieves a blog entry by its unique identifier. + * + * @param id the unique identifier of the blog + * @return a Mono emitting the blog with the specified ID, or empty if not found + */ public Mono getBlogById(String id) { return blogRepository.findById(id); } + /** + * Retrieves all blogs authored by the specified author. + * + * @param author the name of the author whose blogs are to be retrieved + * @return a Flux emitting all Blog entries written by the given author + */ public Flux getBlogsByAuthor(String author) { return blogRepository.findByAuthor(author); } + /** + * Updates an existing blog with new title, content, and author information. + * + * @param id the unique identifier of the blog to update + * @param blog the blog object containing updated fields + * @return a Mono emitting the updated Blog, or empty if the blog does not exist + */ public Mono updateBlog(String id, Blog blog) { return blogRepository.findById(id) .flatMap(existingBlog -> { @@ -38,6 +73,12 @@ public Mono updateBlog(String id, Blog blog) { }); } + /** + * Deletes the blog entry with the specified ID. + * + * @param id the unique identifier of the blog to delete + * @return a Mono signaling completion when the blog is deleted + */ public Mono deleteBlog(String id) { return blogRepository.deleteById(id); } diff --git a/reactive/src/main/java/com/example/reactive/EpisodeController.java b/reactive/src/main/java/com/example/reactive/EpisodeController.java index 3674df2..3e9e619 100644 --- a/reactive/src/main/java/com/example/reactive/EpisodeController.java +++ b/reactive/src/main/java/com/example/reactive/EpisodeController.java @@ -29,47 +29,15 @@ public class EpisodeController { private final Tracer tracer; // from micrometer private final Logger logger = LoggerFactory.getLogger(EpisodeController.class); - /* @GetMapping - public Mono>> getEpisodes() { - // Manually create and start a span - Span newSpan = tracer.nextSpan().name("fetch-episodes").start(); - try (Tracer.SpanInScope ws = tracer.withSpan(newSpan)) { - - return webClient.get() - .uri("https://apissa.sampleapis.com/futurama/episodexxs") // Intentionally faulty for error testing - .retrieve() - .bodyToFlux(EpisodeResponse.class) - .map(ep -> new CustomEpisode(ep.title, ep.writers, ep.originalAirDate, ep.desc, ep.id)) - .collectList() - .map(ResponseEntity::ok) - .doOnSuccess(res -> { - newSpan.tag("episodes.success", "true"); - newSpan.event("Successfully fetched episodes"); - newSpan.end(); - }) - .doOnError(e -> { - newSpan.tag("episodes.success", "false"); - newSpan.error(e); - newSpan.end(); - }) - .onErrorResume(e -> { - String traceId = newSpan.context().traceId(); - -// logger.error("Error fetching episodes. Trace ID: {}", traceId, e); - - CustomEpisode errorEpisode = new CustomEpisode( - "Error occurred", "", "", "Trace ID: " + traceId + ", error: " + e.getMessage(), -1 - ); - return Mono.just(ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) - .body(Collections.singletonList(errorEpisode))); - }); - - } catch (Exception e) { - newSpan.error(e); - newSpan.end(); - throw e; - } - }*/ + /** + * Handles HTTP GET requests to retrieve a list of Futurama episodes from an external API, propagating the current trace ID for distributed tracing. + * + * If the external API call succeeds, returns a list of episodes wrapped in a 200 OK response. If an error occurs, returns a 500 response containing a single episode entry describing the error and including the trace ID for troubleshooting. + * + * The trace ID is propagated via Reactor's context and included in error responses and logs for observability. + * + * @return a reactive Mono emitting a ResponseEntity containing either the list of episodes or an error description with trace information + */ @GetMapping public Mono>> getEpisodes() { @@ -105,6 +73,14 @@ public Mono>> getEpisodes() { } + /** + * Performs a GET request to an external API and returns a response containing the current trace ID. + * + * The trace ID from the current span is propagated through Reactor's context and included in the response. + * On error, returns a 500 response with the error message and trace ID. + * + * @return a Mono emitting a ResponseEntity with a success or error message including the trace ID + */ public Mono> callApiWithTrace(WebClient webClient, Tracer tracer) { String traceId = tracer.currentSpan() != null ? tracer.currentSpan().context().traceId() diff --git a/reactive/src/main/java/com/example/reactive/ReactiveApplication.java b/reactive/src/main/java/com/example/reactive/ReactiveApplication.java index ff5de4e..abb1720 100644 --- a/reactive/src/main/java/com/example/reactive/ReactiveApplication.java +++ b/reactive/src/main/java/com/example/reactive/ReactiveApplication.java @@ -6,6 +6,11 @@ @SpringBootApplication public class ReactiveApplication { + /** + * Launches the Spring Boot application. + * + * @param args command-line arguments passed to the application + */ public static void main(String[] args) { SpringApplication.run(ReactiveApplication.class, args); } diff --git a/reactive/src/main/java/com/example/reactive/sample/CustomEpisode.java b/reactive/src/main/java/com/example/reactive/sample/CustomEpisode.java index 3fbbba4..c5308ff 100644 --- a/reactive/src/main/java/com/example/reactive/sample/CustomEpisode.java +++ b/reactive/src/main/java/com/example/reactive/sample/CustomEpisode.java @@ -7,6 +7,15 @@ public class CustomEpisode { public String description; public int id; + /** + * Constructs a CustomEpisode with the specified title, writers, publish date, description, and ID. + * + * @param title the episode's title + * @param writers the episode's writers + * @param publishDate the episode's publish date + * @param description a brief description of the episode + * @param id the unique identifier for the episode + */ public CustomEpisode(String title, String writers, String publishDate, String description, int id) { this.title = title; this.writers = writers; diff --git a/reactive/src/main/java/com/example/reactive/sample/TracingConfig.java b/reactive/src/main/java/com/example/reactive/sample/TracingConfig.java index e23dfa9..fbff741 100644 --- a/reactive/src/main/java/com/example/reactive/sample/TracingConfig.java +++ b/reactive/src/main/java/com/example/reactive/sample/TracingConfig.java @@ -13,6 +13,11 @@ @Configuration public class TracingConfig { + /** + * Creates and configures a Tracer bean for distributed tracing using OpenTelemetry with span data exported to logs. + * + * @return a Tracer instance set up with a logging span exporter and current trace context management + */ @Bean public Tracer tracer() { SdkTracerProvider sdkTracerProvider = SdkTracerProvider.builder() diff --git a/reactive/src/main/java/com/example/reactive/sample/WebClientConfig.java b/reactive/src/main/java/com/example/reactive/sample/WebClientConfig.java index 33c2c24..fa479ba 100644 --- a/reactive/src/main/java/com/example/reactive/sample/WebClientConfig.java +++ b/reactive/src/main/java/com/example/reactive/sample/WebClientConfig.java @@ -7,6 +7,11 @@ @Configuration public class WebClientConfig { + /** + * Provides a configured {@link WebClient} bean for use in the application. + * + * @return a built {@link WebClient} instance + */ @Bean public WebClient webClient(WebClient.Builder builder) { return builder.build();