DEV Community

Cover image for Full Stack Reddit Clone - Spring Boot, React, Electron App - Part 7
MaxiCB
MaxiCB

Posted on • Updated on

Full Stack Reddit Clone - Spring Boot, React, Electron App - Part 7

Full Stack Reddit Clone - Spring Boot, React, Electron App - Part 7

Introduction

Welcome to Part 7 of creating a Reddit clone using Spring Boot, and React.

What are we building in this part?

  • Comment Request DTO
  • Comment Response DTO
  • Update Comment Repository
  • Comment Service
  • READ Comment Endpoint's
  • CREATE Comment Endpoint

In Part 6 we added some custom exceptions, and made our post endpoint's!

Important Links

Part 1: Comment DTO's 📨

Let's cover our the various DTO's we will need for comments. Inside com.your-name.backend.dto we will create the following classes.

  • CommentRequest: Handles creation of the data that will be sent from the client to the API.
package com.maxicb.backend.dto;

import com.maxicb.backend.model.Post;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;


@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class CommentRequest {
    private Long id;
    private String text;
    private Post post;
}
Enter fullscreen mode Exit fullscreen mode
  • CommentResponse: Handles creation of the data that will be sent to the client from the API.
package com.maxicb.backend.dto;

import com.maxicb.backend.model.User;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.time.Instant;

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class CommentResponse {
    private Long id;
    private String text;
    private Long postId;
    private Instant creationDate;
    private User user;
}
Enter fullscreen mode Exit fullscreen mode

Part 2: Update Comment Repository 📨

Let's cover updating our comment repository to support pagination, and sorting. Inside com.your-name.backend.repository we will Update the following classes.

  • CommentRepository
package com.maxicb.backend.repository;

import com.maxicb.backend.model.Comment;
import com.maxicb.backend.model.Post;
import com.maxicb.backend.model.User;
import org.springframework.data.repository.PagingAndSortingRepository;

import java.util.List;

public interface CommentRepository extends PagingAndSortingRepository<Comment, Long> {
    List<Comment> findByPost(Post post);

    List<Comment> findAllByUser(User user);
}

Enter fullscreen mode Exit fullscreen mode

Part 3: Comment Service 🌎

Let's cover the comment service our application will have. Inside com.your-name.backend.services add the following class.

  • CommentService: Hold the logic for mapping data to and from DTO's, getting all comments's by postId, getting user specific comments's, and adding comments's to post's.
package com.maxicb.backend.service;

import com.github.marlonlom.utilities.timeago.TimeAgo;
import com.maxicb.backend.dto.CommentRequest;
import com.maxicb.backend.dto.CommentResponse;
import com.maxicb.backend.exception.PostNotFoundException;
import com.maxicb.backend.exception.UserNotFoundException;
import com.maxicb.backend.model.Comment;
import com.maxicb.backend.model.Post;
import com.maxicb.backend.model.User;
import com.maxicb.backend.repository.CommentRepository;
import com.maxicb.backend.repository.PostRepository;
import com.maxicb.backend.repository.UserRepository;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Instant;
import java.util.List;
import java.util.stream.Collectors;

@Service
@AllArgsConstructor
@Transactional
public class CommentService {
    private final UserRepository userRepository;
    private final PostRepository postRepository;
    private final CommentRepository commentRepository;
    private final AuthService authService;

    private CommentResponse mapToResponse(Comment comment) {
        return CommentResponse.builder()
                .id(comment.getId())
                .text(comment.getText())
                .postId(comment.getPost().getPostId())
                .creationDate(TimeAgo.using(comment.getCreationDate().toEpochMilli()))
                .userName(comment.getUser().getUsername())
                .build();
    }

    private Comment mapToComment(CommentRequest commentRequest) {
        User user = authService.getCurrentUser();
        Post post = postRepository.findById(commentRequest.getPostId())
                .orElseThrow(() -> new PostNotFoundException("Post not found with id: " + commentRequest.getPostId()));
        return Comment.builder()
                .text(commentRequest.getText())
                .post(post)
                .creationDate(Instant.now())
                .user(user)
                .build();
    }

    public CommentResponse save(CommentRequest commentRequest) {
        return mapToResponse(commentRepository.save(mapToComment(commentRequest)));
    }

    public List<CommentResponse> getCommentsForPost(Long id) {
        Post post = postRepository.findById(id)
                .orElseThrow(() -> new PostNotFoundException("Post not found with id: " + id));
        return commentRepository.findByPost(post)
                .stream()
                .map(this::mapToResponse)
                .collect(Collectors.toList());
    }

    public List<CommentResponse> getCommentsForUser(Long id) {
        User user = userRepository.findById(id)
                .orElseThrow(() -> new UserNotFoundException("User not found with id: " + id));
        return commentRepository.findAllByUser(user)
                .stream()
                .map(this::mapToResponse)
                .collect(Collectors.toList());
    }
}
Enter fullscreen mode Exit fullscreen mode

Part 4: Comment Controller 🌐

Let's cover the comment controller our application will have. Inside com.your-name.backend.controller add the following class.

  • CommentController: Hold the endpoints for fetching creating comments, fetching comments on a post, and specific user comments.
package com.maxicb.backend.controller;

import com.maxicb.backend.dto.CommentRequest;
import com.maxicb.backend.dto.CommentResponse;
import com.maxicb.backend.service.CommentService;
import lombok.AllArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/api/comments")
@AllArgsConstructor
public class CommentController {
    private final CommentService commentService;

    @PostMapping
    public ResponseEntity<CommentResponse> addComment(@RequestBody CommentRequest commentRequest) {
        return new ResponseEntity<>(commentService.save(commentRequest), HttpStatus.CREATED);
    }

    @GetMapping("/post/{id}")
    public ResponseEntity<List<CommentResponse>> getCommentsByPost(@PathVariable Long id) {
        return new ResponseEntity<>(commentService.getCommentsForPost(id), HttpStatus.OK);
    }

    @GetMapping("/user/{id}")
    public ResponseEntity<List<CommentResponse>> getCommentsByUser(@PathVariable Long id) {
        return new ResponseEntity<>(commentService.getCommentsForUser(id), HttpStatus.OK);
    }
}
Enter fullscreen mode Exit fullscreen mode

Conclusion 🔍

  • To ensure everything is configured correctly you can run the application, and ensure there are no error in the console. Towards the bottom of the console you should see output similar to below

Alt Text

  • If there are no error's in the console you can test the comment creation logic by sending a post request to http://localhost:8080/api/comments with the following data. You will still have to follow the same steps covered in the previous parts to login to an account to make post's, as well as create a subreddit, and valid post to add a comment to.
{
    "postId": <post-id>,
    "text": "My First Comment!!"
}
Enter fullscreen mode Exit fullscreen mode
  • In this article we added the CREATE && READ endpoints for creating and reading comments!.

Next

Voting System! Part 8

Latest comments (1)

Collapse
 
spartan1cs profile image
spartan1cs

Eagerly waiting for part 8. Please post