본문 바로가기

카테고리 없음

자바로 스웨거 추가, No operations defined in spec!로 인한 Todo 수정

implementation("org.springdoc:springdoc-openapi-starter-webmvc-ui:2.2.0")

 

이걸 넣어주고

package com.teamsparta.infra;

import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class SwaggerConfig {

    @Bean
    public OpenAPI openAPI() {
        return new OpenAPI()
                .components(new Components())
                .info(new Info()
                        .title("Todo API")
                        .description("Todo API schema")
                        .version("1.0.0"));
    }
}

 

이걸 추가한다.

 

그리고  http://localhost:8080/swagger-ui.html 이걸 입력한다. 그럼 접속은 된다.

 

근데 접속만 되고 컨트롤러가 인식이 안되는거 아닌가?

 

No operations defined in spec! 이건만 떠서 당황하고 고치려고 계속 시도한 결과, 

 

내가 경로설정을 잘못했다는걸 깨달았다!

 

SwaggerConfig는 메인 어플리케이션 밑에 있는 녀석을 불러들인다. 그래서 전부 메인 아래에 소속되어 있어야만 한다.

 

그런데, 난 깜빡해서 동등하게 해버려서 작성한건 전부 메인이 소속된 패키지의 하위 패키지로 몰아넣었다.

이런식으로 말이다.

 

그런데 그렇게 하위 패키지로 옮기자

eror starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled.
2024-07-19T16:32:01.719+09:00 ERROR 21632 --- [           main] o.s.boot.SpringApplication               : Application run failed

 

이오류로 작동이 되지 않았는데 그 이유는 Spring Boot가 동일한 클래스일땐 인식이 됬지만 하위로 옮기자 인식을 못해서 인식을 시켜주기 위해

@Getter
@Setter
@NoArgsConstructor
@Entity// 꼭 추가하자!!

public class Todo {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)//반드시 필요
    private Long id; // 고유 id
    private String title;// 제목
    private String content;//내용
    private String assignee;//담당자
    private String password;//비번
    private Date createdAt;//작성일
}

 

이렇게 @Entity랑 @Id @GeneratedValue(strategy = GenerationType.IDENTITY)를 엔티티에 추가하는걸로 인식을 시켜서 해결을 했다.

 

그리고 스웨거로 연결해봤을때 수정도

@Setter
@Getter
public class TodoRequestDTO {
    private String title;
    private String content;
    private String assignee;
    private String password;
}

 

이걸 쓰다보니 수정할때 비번도 같이 수정이 되서 한번 할때마다 비번이 바뀌기 때문에 삭제할때 귀찮아지다보니

@Getter
@Setter
public class TodoUpdateDTO {
    private String title;
    private String content;
    private String assignee;
}//한번 수정하면 비번까지 바뀌는 현상 때문에 비번을 유지하기 위해 만듬

 

이렇게 수정용을 만들어주고 서비스, 서비스 임플도

@Override
    public TodoResponseDTO update(Long id, TodoUpdateDTO todoUpdateDTO, String password) {
//비번, 아이디, 리퀘스트를 받아 리스폰스를 반환
//    public Todo update(Long id, TodoRequestDTO todoRequestDTO, String password) {
        Todo existingTodo = todoRepository.findById(id)//아이디 찾고 없으면 예외
                .orElseThrow(() -> new RuntimeException("Todo not found"));

        if (!existingTodo.getPassword().equals(password)) {//비번 안맞으면 예외
            throw new RuntimeException("Invalid password");
        }
//dto의 getter, setter 덕분에 사용
        existingTodo.setTitle(todoUpdateDTO.getTitle());//todoRequestDTO의 getTitle()를 호출하여 할 일의 제목을 가져옴
        existingTodo.setContent(todoUpdateDTO.getContent());
        existingTodo.setAssignee(todoUpdateDTO.getAssignee());

//        existingTodo.setPassword(todoUpdateDTO.getPassword());// 비밀번호는 이제 수정 안함


        Todo updatedTodo = todoRepository.save(existingTodo);
        return convertToResponseDTO(updatedTodo); // Todo를 TodoResponseDTO로 변환
        //        return todoRepository.save(existingTodo);

    }

requestdto랑 연결된걸 전부 updatedto로 바꾸고 컨트롤러에서도 똑같이 수행했다.

 

그리고 깔끔한 설명을 추가하기 위해

@Operation(summary = "새로운 할일 생성", description = "새 할일을 만드시오")

 

이런식으로 설명도 추가했다.

package com.teamsparta.task.controller;

import com.teamsparta.task.dto.TodoRequestDTO;
import com.teamsparta.task.dto.TodoResponseDTO;
import com.teamsparta.task.dto.TodoUpdateDTO;
import com.teamsparta.task.service.TodoService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/api/todos")
@RequiredArgsConstructor
public class TodoController {

    private final TodoService todoService;


    @Operation(summary = "새로운 할일 생성", description = "새 할일을 만드시오")
    //summary는 제목, description는 내용
    @PostMapping
    public ResponseEntity<TodoResponseDTO> createTodo(@RequestBody TodoRequestDTO todoRequestDTO )
    {//TodoRequestDTO를 입력받아 todo 생성
        TodoResponseDTO createdTodo = todoService.create(todoRequestDTO);//서비스를 통해 리퀘스트로 생성, 리스폰스 반환
        return ResponseEntity.status(HttpStatus.CREATED).body(createdTodo);//완료하면 201 반환
    }

    @Operation(summary = "개별 조회", description = "조회할 ID를 입력하시오")
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "Todo found"),
            @ApiResponse(responseCode = "404", description = "Todo not found")
    })
    @GetMapping("/{id}")
    public ResponseEntity<TodoResponseDTO> getTodo(@PathVariable Long id) {
        TodoResponseDTO todoResponseDTO = todoService.get(id);
        return ResponseEntity.ok(todoResponseDTO);//완료시 리스폰스 보여줌
    }


    @Operation(summary = "전체 조회", description = "그냥 보시오")
    @GetMapping
    public ResponseEntity<List<TodoResponseDTO>> getAllTodos() {
        List<TodoResponseDTO> todoResponseDTOs = todoService.getAll();
        return ResponseEntity.ok(todoResponseDTOs);
    }

    //Request를 UpdateDto로 수정
    @Operation(summary = "할일 수정", description = "ID를 입력하고 제목, 내용, 담당자 중 아무거나 수정하세요")
    @PutMapping("/{id}")
    public ResponseEntity<TodoResponseDTO> updateTodo(@PathVariable Long id, @RequestBody TodoUpdateDTO todoUpdateDTO, @RequestParam String password) {
        TodoResponseDTO updatedTodoResponseDTO = todoService.update(id, todoUpdateDTO, password);
        return ResponseEntity.ok(updatedTodoResponseDTO);
    }

    @Operation(summary = "할일 삭제", description = "삭제할 할일의 ID를 입력하시오")
    @DeleteMapping("/{id}")
    public ResponseEntity<Void> deleteTodo(@PathVariable Long id, @RequestParam String password) {
        todoService.delete(id, password);
        return ResponseEntity.noContent().build();
    }
}

 

그래서 이렇게 설명을 추가하고 수정도 UpdateDto로 바꿔서 완성