Skip to content

Commit c02e4e9

Browse files
author
zahar.kalosha
committed
Add questionDTOs and move all business logic from Controller to service
1 parent 095cf1c commit c02e4e9

File tree

5 files changed

+131
-32
lines changed

5 files changed

+131
-32
lines changed
Lines changed: 14 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,40 @@
11
package com.example.postgresdemo.controller;
22

3-
import com.example.postgresdemo.exception.ResourceNotFoundException;
4-
import com.example.postgresdemo.model.Question;
5-
import com.example.postgresdemo.repository.QuestionRepository;
3+
import com.example.postgresdemo.model.QuestionRequestDTO;
4+
import com.example.postgresdemo.model.QuestionResponseDTO;
5+
import com.example.postgresdemo.service.QuestionService;
66
import org.springframework.beans.factory.annotation.Autowired;
77
import org.springframework.data.domain.Page;
88
import org.springframework.data.domain.Pageable;
99
import org.springframework.http.ResponseEntity;
1010
import org.springframework.web.bind.annotation.*;
11+
1112
import javax.validation.Valid;
1213

1314
@RestController
14-
public class QuestionController {
1515

16+
public class QuestionController {
1617
@Autowired
17-
private QuestionRepository questionRepository;
18+
private QuestionService questionService;
1819

1920
@GetMapping("/questions")
20-
public Page<Question> getQuestions(Pageable pageable) {
21-
return questionRepository.findAll(pageable);
21+
public Page<QuestionResponseDTO> getQuestions(Pageable pageable) {
22+
return questionService.findAll(pageable);
2223
}
2324

24-
2525
@PostMapping("/questions")
26-
public Question createQuestion(@Valid @RequestBody Question question) {
27-
return questionRepository.save(question);
26+
public QuestionResponseDTO createQuestion(@Valid @RequestBody QuestionRequestDTO question) {
27+
return questionService.create(question);
2828
}
2929

3030
@PutMapping("/questions/{questionId}")
31-
public Question updateQuestion(@PathVariable Long questionId,
32-
@Valid @RequestBody Question questionRequest) {
33-
return questionRepository.findById(questionId)
34-
.map(question -> {
35-
question.setTitle(questionRequest.getTitle());
36-
question.setDescription(questionRequest.getDescription());
37-
return questionRepository.save(question);
38-
}).orElseThrow(() -> new ResourceNotFoundException("Question not found with id " + questionId));
31+
public QuestionResponseDTO updateQuestion(@PathVariable Long questionId,
32+
@Valid @RequestBody QuestionRequestDTO questionRequest) {
33+
return questionService.update(questionId, questionRequest);
3934
}
4035

41-
4236
@DeleteMapping("/questions/{questionId}")
4337
public ResponseEntity<?> deleteQuestion(@PathVariable Long questionId) {
44-
return questionRepository.findById(questionId)
45-
.map(question -> {
46-
questionRepository.delete(question);
47-
return ResponseEntity.ok().build();
48-
}).orElseThrow(() -> new ResourceNotFoundException("Question not found with id " + questionId));
38+
return questionService.delete(questionId);
4939
}
5040
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package com.example.postgresdemo.model;
2+
3+
import javax.validation.constraints.NotBlank;
4+
import javax.validation.constraints.Size;
5+
6+
public class QuestionRequestDTO {
7+
@NotBlank
8+
@Size(min = 3, max = 100)
9+
private String title;
10+
11+
private String description;
12+
13+
public String getTitle() {
14+
return title;
15+
}
16+
17+
public void setTitle(String title) {
18+
this.title = title;
19+
}
20+
21+
public String getDescription() {
22+
return description;
23+
}
24+
25+
public void setDescription(String description) {
26+
this.description = description;
27+
}
28+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package com.example.postgresdemo.model;
2+
3+
public class QuestionResponseDTO {
4+
private Long id;
5+
private String body;
6+
7+
public Long getId() {
8+
return id;
9+
}
10+
11+
public void setId(Long id) {
12+
this.id = id;
13+
}
14+
15+
public String getBody() {
16+
return body;
17+
}
18+
19+
public void setBody(String body) {
20+
this.body = body;
21+
}
22+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package com.example.postgresdemo.service;
2+
3+
import com.example.postgresdemo.exception.ResourceNotFoundException;
4+
import com.example.postgresdemo.model.Question;
5+
import com.example.postgresdemo.model.QuestionRequestDTO;
6+
import com.example.postgresdemo.model.QuestionResponseDTO;
7+
import com.example.postgresdemo.repository.QuestionRepository;
8+
import org.springframework.beans.factory.annotation.Autowired;
9+
import org.springframework.data.domain.Page;
10+
import org.springframework.data.domain.Pageable;
11+
import org.springframework.http.ResponseEntity;
12+
import org.springframework.stereotype.Service;
13+
14+
@Service
15+
public class QuestionService {
16+
@Autowired
17+
private QuestionRepository questionRepository;
18+
19+
public Page<QuestionResponseDTO> findAll(Pageable pageable) {
20+
return questionRepository.findAll(pageable)
21+
.map(this::toQuestionResponseDTO);
22+
}
23+
24+
public QuestionResponseDTO create(QuestionRequestDTO questionRequest) {
25+
Question question = toQuestion(questionRequest);
26+
return toQuestionResponseDTO(questionRepository.save(question));
27+
}
28+
29+
public QuestionResponseDTO update(Long questionId, QuestionRequestDTO questionRequest) {
30+
Question question = toQuestion(questionRequest);
31+
return questionRepository.findById(questionId)
32+
.map(foundQuestion -> {
33+
foundQuestion.setTitle(question.getTitle());
34+
foundQuestion.setDescription(question.getDescription());
35+
return toQuestionResponseDTO(questionRepository.save(foundQuestion));
36+
}).orElseThrow(() -> new ResourceNotFoundException("Question not found with id " + questionId));
37+
38+
}
39+
40+
public ResponseEntity<?> delete(Long questionId) {
41+
return questionRepository.findById(questionId)
42+
.map(question -> {
43+
questionRepository.delete(question);
44+
return ResponseEntity.ok().build();
45+
}).orElseThrow(() -> new ResourceNotFoundException("Question not found with id " + questionId));
46+
}
47+
48+
private QuestionResponseDTO toQuestionResponseDTO(Question question) {
49+
QuestionResponseDTO questionResponse = new QuestionResponseDTO();
50+
questionResponse.setId(question.getId());
51+
questionResponse.setBody(question.getTitle() + "\n" + question.getDescription());
52+
53+
54+
return questionResponse;
55+
}
56+
57+
private Question toQuestion(QuestionRequestDTO questionRequestDTO) {
58+
Question question = new Question();
59+
question.setTitle(questionRequestDTO.getTitle());
60+
question.setDescription(questionRequestDTO.getDescription());
61+
return question;
62+
}
63+
}

src/test/java/com/example/postgresdemo/controller/QuestionControllerTest.java

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -79,16 +79,15 @@ void testCreateCorrectQuestion() throws Exception {
7979
"}"))
8080
.andExpect(status().isOk())
8181
.andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE))
82-
.andExpect(MockMvcResultMatchers.jsonPath("$.title", Matchers.equalTo("Question 1")))
83-
.andExpect(MockMvcResultMatchers.jsonPath("$.description", Matchers.equalTo("Description 1")));
82+
.andExpect(MockMvcResultMatchers.jsonPath("$.body", Matchers.equalTo("Question 1\nDescription 1")));
8483
}
8584

8685
@Test
8786
void testCreateQuestionWithoutTitle() throws Exception {
8887
mockMvc.perform(MockMvcRequestBuilders.post("/questions")
8988
.contentType(MediaType.APPLICATION_JSON)
9089
.content("{\n" +
91-
" \"description\": \"Description\"\n" +
90+
" \"body\": \"\\nDescription\"\n" +
9291
"}"))
9392
.andExpect(status().is4xxClientError());
9493
}
@@ -127,9 +126,7 @@ void testCreateQuestionWithoutDescription() throws Exception {
127126
"}"))
128127
.andExpect(status().isOk())
129128
.andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE))
130-
.andExpect(MockMvcResultMatchers.jsonPath("$.title", Matchers.equalTo("Question 1")))
131-
.andExpect(MockMvcResultMatchers.jsonPath("$.description", Matchers.equalTo(null)));
132-
}
129+
.andExpect(MockMvcResultMatchers.jsonPath("$.body", Matchers.equalTo("Question 1\nnull")));}
133130

134131
@Test
135132
void testUpdateQuestion() throws Exception {
@@ -144,8 +141,7 @@ void testUpdateQuestion() throws Exception {
144141
"}"))
145142
.andExpect(status().isOk())
146143
.andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE))
147-
.andExpect(MockMvcResultMatchers.jsonPath("$.title", Matchers.equalTo("Edited Question 1")))
148-
.andExpect(MockMvcResultMatchers.jsonPath("$.description", Matchers.equalTo("Edited Description 1")));
144+
.andExpect(MockMvcResultMatchers.jsonPath("$.body", Matchers.equalTo("Edited Question 1\nEdited Description 1")));
149145
}
150146

151147
@Test

0 commit comments

Comments
 (0)