오늘 한 일
오늘도 유사 당근마켓(햇살마켓) 개발을 계속 했다
1. User → Seller로 변경
UserId를 Item에 넣어두고 있었는데 판매자 프로필과 구매자 프로필을 따로따로 하기로 해서 Item에는 User대신 Seller를 넣었다
2. 주문(구매 요청) 기능 만들기 주문 CRUD는 오늘 다 했다!
내일 할 일
주문 승인처리, 배송 완료처리
1. User → Seller로 변경
@ManyToOne
@JoinColumn(name = "seller_id")
private Seller seller;
전에 User였던 것을 Seller로 바꾸니까 그냥 됐음
2. 주문(구매 요청) 기능 만들기
2-1. Order Entity를 생성함
@Getter
@Entity
@Table(name = "orders")
public class Order {
private final int ORDER_PENDING = 1;
private final int ORDER_ACCEPTED = 2;
private final int ORDER_REJECTED = 3;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@JoinColumn(name = "item_id")
private Item item;
@JoinColumn(name = "buyer_id")
private Buyer buyer;
private int orderStatus;
}
Order의 진행 상황을 어떻게 표시할지 생각하다가 상태 코드를 만들고 그걸 상수로 만들어서 상태 업데이트 함수로 orderStatus에 값 넣어주기로 함
아 근데 나는 Column 안 붙이면 db에 안 들어가는줄 알고
이래놨는데 db에 order_accepted, order_pending, order_rejected가 다 들어가있음ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ
public class Order extends Timestamped {
// private final String ORDER_PENDING = "Pending";
// private final String ORDER_ACCEPTED = "Accepted";
// private final String ORDER_REJECTED = "Rejected";
그래서 그냥 삭제하고 String값으로 함 내일 Enum을 공부하고 다시 해보기로 했음
⛳문제 : 그렇게 하고 나니까 Item에 오류가 뜸
basic attribute type should not be ‘attribute entity’
🚩해결 : @ManyToOne 달아주니까 사라졌다
item이 삭제될때 그거에 딸린 orders도 삭제되어야 하니까 cascade를 Item에다 달아줌
@OneToMany
@JoinColumn(name = "item_id")
private List<Order> orders;
@OneToMany(mappedBy = "item",cascade = CascadeType.PERSIST,orphanRemoval = true)
@JoinColumn(name = "item_id")
private List<Order> orders;
이렇게 만들어줌!
item이 삭제되면 거기에 딸린 order들도 삭제되도록
🚩문제 : 실행이 안 됨
with name 'webSecurityConfig' defined in file [E:\Workspace\Temp\SunlightMarket\build\classes\java\main\com\raincloud\sunlightmarket\global\config\WebSecurityConfig.class]: Unsatisfied dependency expressed through constructor parameter 1: Error creating bean with name 'userDetailsServiceImpl' defined in file [E:\Workspace\Temp\SunlightMarket\build\classes\java\main\com\raincloud\sunlightmarket\global\security\UserDetailsServiceImpl.class]: Unsatisfied dependency expressed through constructor parameter 0: Error creating bean with name 'userRepository' defined in com.raincloud.sunlightmarket.user.repository.UserRepository defined in @EnableJpaRepositories declared on JpaRepositoriesRegistrar.EnableJpaRepositoriesConfiguration: Cannot resolve reference to bean 'jpaSharedEM_entityManagerFactory' while setting bean property 'entityManager’
Cannot resolve reference to bean 'jpaSharedEM_entityManagerFactory' while setting bean property 'entityManager’
구글링함
Exception says that there is no bean with name entityManagerFactory, Place a debug point in
public LocalContainerEntityManagerFactoryBean entityManagerFactory(
EntityManagerFactoryBuilder factoryBuilder)
method org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration.class and check why the bean is not getting initiated.
Oh, From discussion I came to the conclusion that mentioned issue is due to hibernate older dependencies. Also, the @Id which was imported needs to be from javax.persistence.id for all your entities.
Association 'com.raincloud.sunlightmarket.item.entity.Item.orders' is 'mappedBy' another entity and may not specify the '@JoinColumn' at org.hibernate.boot.model.internal.CollectionBinder.detectMappedByProblem(CollectionBinder.java:1239) ~[hibernate-core-6.2.13.Final.jar:6.2.13.Final] at org.hibernate.boot.model.internal.CollectionBinder.bind(CollectionBinder.java:1154) ~[hibernate-core-6.2.13.Final.jar:6.2.13.Final] at org.hibernate.boot.model.internal.CollectionBinder.bindCollection(CollectionBinder.java:353) ~[hibernate-core-6.2.13.Final.jar:6.2.13.Final] at org.hibernate.boot.model.internal.PropertyBinder.bindProperty(PropertyBinder.java:873) ~[hibernate-core-6.2.13.Final.jar:6.2.13.Final] at org.hibernate.boot.model.internal.PropertyBinder.buildProperty(PropertyBinder.java:787) ~[hibernate-core-6.2.13.Final.jar:6.2.13.Final] at org.hibernate.boot.model.internal.PropertyBinder.processElementAnnotations(PropertyBinder.java:708) ~[hibernate-core-6.2.13.Final.jar:6.2.13.Final] at org.hibernate.boot.model.internal.EntityBinder.processIdPropertiesIfNotAlready(EntityBinder.java:967) ~[hibernate-core-6.2.13.Final.jar:6.2.13.Final] at org.hibernate.boot.model.internal.EntityBinder.handleIdentifier(EntityBinder.java:302) ~[hibernate-core-6.2.13.Final.jar:6.2.13.Final] at org.hibernate.boot.model.internal.EntityBinder.bindEntityClass(EntityBinder.java:228) ~[hibernate-core-6.2.13.Final.jar:6.2.13.Final] at org.hibernate.boot.model.internal.AnnotationBinder.bindClass(AnnotationBinder.java:417) ~[hibernate-core-6.2.13.Final.jar:6.2.13.Final] at org.hibernate.boot.model.source.internal.annotations.AnnotationMetadataSourceProcessorImpl.processEntityHierarchies(AnnotationMetadataSourceProcessorImpl.java:255) ~[hibernate-core-6.2.13.Final.jar:6.2.13.Final] at org.hibernate.boot.model.process.spi.MetadataBuildingProcess$1.processEntityHierarchies(MetadataBuildingProcess.java:278) ~[hibernate-core-6.2.13.Final.jar:6.2.13.Final] at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:321) ~[hibernate-core-6.2.13.Final.jar:6.2.13.Final] at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:1383) ~[hibernate-core-6.2.13.Final.jar:6.2.13.Final] at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1454) ~[hibernate-core-6.2.13.Final.jar:6.2.13.Final]
⛳해결 :
@OneToMany(mappedBy = "item",cascade = CascadeType.PERSIST,orphanRemoval = true)
@JoinColumn(name = "item_id")
→
@OneToMany(mappedBy = "item",cascade = CascadeType.PERSIST,orphanRemoval = true)
joincolumn 삭제
🚩문제 : references items (item_id)" via JDBC [Failed to add the foreign key constraint. Missing column 'item_id' for constraint 'FK247nnxschdfm8lre0ssvy3k1r' in the referenced table 'items']
alter table orders add constraint FK247nnxschdfm8lre0ssvy3k1r foreign key (item_id) references items (item_id)" via JDBC [Failed to add the foreign key constraint. Missing column 'item_id' for constraint 'FK247nnxschdfm8lre0ssvy3k1r' in the referenced table 'items']
@Table(name = "items")
@NoArgsConstructor
public class Item extends Timestamped {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "item_id")
private Long id;
⛳해결 : name = item_id도 삭제해봄
그러니까 됨
Q. 왜?
🚩문제 :
localhost:8080/api/orders/add?itemId=1
403 인증문제 아니라고 함
ERROR 31240 --- [nio-8080-exec-6] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: java.lang.NullPointerException: Cannot invoke "com.raincloud.sunlightmarket.order.service.OrderService.addOrder(com.raincloud.sunlightmarket.order.dto.OrderRequestDto, java.lang.Long, com.raincloud.sunlightmarket.user.entity.User)" because "this.orderService" is null] with root cause
public class OrderController { private OrderService orderService;
이게 회색으로 뜨고 autowired가 안 됨 왜지…
public OrderController(OrderService orderService){
this.orderService = orderService;
}
이렇게 넣어주니까 회색이 보라색 됨
ERROR 22552 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: java.lang.NullPointerException: Cannot invoke "com.raincloud.sunlightmarket.order.service.OrderService.addOrder(com.raincloud.sunlightmarket.order.dto.OrderRequestDto, java.lang.Long, com.raincloud.sunlightmarket.user.entity.User)" because "this.orderService" is null] with root cause
java.lang.NullPointerException: Cannot invoke "com.raincloud.sunlightmarket.order.service.OrderService.addOrder(com.raincloud.sunlightmarket.order.dto.OrderRequestDto, java.lang.Long, com.raincloud.sunlightmarket.user.entity.User)" because "this.orderService" is null
근데 또 안들어가네 뭐지
⛳해결 : final 추가했더니 보라색 되고 에러 사라지고 잘 동작함
private OrderService orderService → private final OrderService orderService;
Q. 왜죠?
{
"status": 201,
"message": "구매 요청 성공했습니다",
"data": {
"buyerName": null,
"address": "주소주소",
"orderStatus": "Pending"
}
}
🚩문제 : 2023-12-07T17:13:03.025+09:00 WARN 30216 --- [nio-8080-exec-3] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.HttpMediaTypeNotSupportedException: Content-Type 'text/plain;charset=UTF-8' is not supported]
와 근데 희한한게 item 1에는 order가 들어가지고 item 2에는 order이 안 들어가짐
localhost:8080/api/orders/add?itemId=1
→
{
"status": 201,
"message": "구매 요청 성공했습니다",
"data": {
"buyerName": "닉",
"address": "주소주소",
"orderStatus": "PENDING"
}
}
localhost:8080/api/orders/add?itemId=2
→
403forbidden
Resolved [org.springframework.web.HttpMediaTypeNotSupportedException: Content-Type 'text/plain;charset=UTF-8' is not supported]
이 창에서 1로 보내면 또 안 들어감
아까 되던 창에서 2로 보내면 그거는 또 들어감
⛳해결 : 포스트맨에서 JSON이 아니라 text로 보내고 있었음, JSON 으로 보내니까 잘 됨
근데 본인이 본인의 글에다가 댓글을 달 수 있으면 안될 거 같음
private Item getNotUserItemById(Long itemId, User user){
Item item = itemRepository.findById(itemId).orElseThrow(NullPointerException::new);
Seller seller = item.getSeller();
User user = getUserBySeller(seller);
}
💡개선 : 바보같이 Join한 Column을 findBy ... 만들어서 가져오던거 그냥 가져오게 수정함
private User getUserBySeller(Seller seller){
User user = userRepository.findBySellerId(seller.getId()).orElseThrow(NullPointerException::new);
return user;
}
이렇게 하고 있다가 깨달음 그냥 가져올 수 있는 거 같은데…?
item.getSeller().getUser();
itemService에서
public ItemResponseDto addItem(ItemRequestDto requestDto, User user) {
Seller seller = getSellerByUser(user);
...
private Seller getSellerByUser(User user){
Seller seller = sellerRepository.findByUserId(user.getId()).orElseThrow(NullPointerException::new);
return seller;
}
이러고 있었던거 그냥
public ItemResponseDto addItem(ItemRequestDto requestDto, User user) {
Seller seller = user.getSeller();
이렇게 다 수정함
💡발견 !! : ApiResponse로 감싸고 에러 날렸더니
{
"status": 400,
"message": "작성자는 구매 요청을 할 수 없습니다.",
"data": null
}
이렇게 리턴값이 옴
→ 위에서 RejectedError에 상태메시지 넣어서 날렸더니
controller단에서 RejectedError를 catch로 받아서 에러메시지가 출력되는듯 !!
어떻게 할지 고민하고 있었는데 좋았다
NullPointerException도 상태메시지 넣어서 Catch해 버리면 될듯
🚩문제 : .orElseThrow(NullPointerException::new); 저 안에 상태 메시지를 넣은 NullPointerException을 생성할 줄 모름
⛳해결 : 저 :: 이 부분이 람다식이라는 것을 알고 나서 .orElseThrow(()-> new NullPointerException("해당 id로 아이템을 찾을 수 없습니다."))); 이렇게 함
Controller--------
@PostMapping("/add")
public ApiResponse<OrderResponseDto> addOrder(
@RequestBody OrderRequestDto requestDto,
@RequestParam Long itemId,
@AuthenticationPrincipal UserDetailsImpl userDetails
) {
try {
OrderResponseDto responseDto = orderService.addOrder(requestDto,itemId, userDetails.getUser());
return new ApiResponse<OrderResponseDto>(HttpStatus.CREATED.value(),"구매 요청 성공했습니다",responseDto);
}catch (RejectedExecutionException | IllegalArgumentException ex){
return new ApiResponse<OrderResponseDto>(HttpStatus.BAD_REQUEST.value(),ex.getMessage());
}
}
Service----------
public OrderResponseDto addOrder(OrderRequestDto requestDto, Long itemId , User user)
{
Item item = getNotUserItemById(itemId,user);
Buyer buyer = user.getBuyer();
Order order = new Order(requestDto,item,buyer);
orderRepository.save(order);
return new OrderResponseDto(order);
}
private Item getNotUserItemById(Long itemId, User user){
Item item = itemRepository.findById(itemId).orElseThrow(Item item = itemRepository.findById(itemId).orElseThrow(()-> new NullPointerException("해당 id로 아이템을 찾을 수 없습니다.")););
User userFound = item.getSeller().getUser();
if(userFound.getId().equals(user.getId())){
throw new RejectedExecutionException("작성자는 구매 요청을 할 수 없습니다.");
}
return item;
}
Result-------------
{
"status": 400,
"message": "작성자는 구매 요청을 할 수 없습니다.",
"data": null
}
저렇게 하니까 NullPointerException도 받아서 ApiResponse로 상태메시지 출력되어짐!!
💡개선 : 아이템(판매글)작성자가 댓글(구매요청)을 달지 못하게 하기 위해서
public OrderResponseDto addOrder(OrderRequestDto requestDto, Long itemId , User user)
{
Item item = getNotUserItemById(itemId,user);
Buyer buyer = getBuyerByUser(user);
Order order = new Order(requestDto,item,buyer);
orderRepository.save(order);
return new OrderResponseDto(order);
}
private Item getItemById(Long itemId){
Item item = itemRepository.findById(itemId).orElseThrow(NullPointerException::new);
return item;
}
→
private Item getNotUserItemById(Long itemId, User user){
Item item = itemRepository.findById(itemId).orElseThrow(NullPointerException::new);
User userFound = item.getSeller().getUser();
if(userFound.getId().equals(user.getId())){
throw new RejectedExecutionException("작성자는 구매 요청을 할 수 없습니다.");
}
return item;
}
이렇게 수정함
그러고 나니까 자기 Item 조회할때는 그 Item에 들어온 요청목록을 보이게 하고 싶어졌음
남의 Item을 볼 때나 비로그인시에는 안 보이고
나는 Filter에서 조회하는 부분을 걸러버렸는데 저 부분을 어떻게 구현할지 생각해 보다가
혹시 method주소랑 path가 같아도 parameter가 다르면 오버라이딩 되나 싶어짐
근데 controller로 요청이 들어오기 전에 filter에서 걸러버린다는데 로그인을 안 했는데 Authentication이 되나..?
아니다 남들도 요청을 볼 수 있으면 되나..?
try {
ItemAllResponseDto responseDto = new ItemAllResponseDto();
responseDto.setItemResponseDtos(itemService.getAllItems());
return new ApiResponse<ItemAllResponseDto>(HttpStatus.OK.value(),"아이템 조회에 성공했습니다",responseDto);
}catch (RejectedExecutionException | IllegalArgumentException | NullPointerException ex){
return new ApiResponse<ItemAllResponseDto>(HttpStatus.BAD_REQUEST.value(),ex.getMessage());
}
Controller
@GetMapping("/read")
public ApiResponse<List<OrderResponseDto>> getOrdersForAll(
@RequestParam Long itemId
) {
try {
List<OrderResponseDto> responseDto = orderService.getOrders(itemId);
return new ApiResponse<List<OrderResponseDto>>(HttpStatus.OK.value(),"구매 요청 성공했습니다",responseDto);
}catch (RejectedExecutionException | NullPointerException ex){
return new ApiResponse<List<OrderResponseDto>>(HttpStatus.BAD_REQUEST.value(),ex.getMessage());
}
}
Service
public List<OrderResponseDto> getOrders(Long itemId){
return orderRepository.findAllByItemId(itemId).stream()
.map(OrderResponseDto::new)
.collect(Collectors.toList());
}
⛳문제 : 웃긴게 1개만 들어있는 Order는 반환이 되는데
한 Item에 Order이 2개 이상 들어있으면 안 됨
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: org.springframework.dao.IncorrectResultSizeDataAccessException: query did not return a unique result: 2] with root cause
Item은 어케한거야
jakarta.persistence.NonUniqueResultException: query did not return a unique result: 2 at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:128) ~[hibernate-core-6.2.13.Final.jar:6.2.13.Final] at org.hibernate.query.spi.AbstractSelectionQuery.getSingleResult(AbstractSelectionQuery.java:482) ~[hibernate-core-6.2.13.Final.jar:6.2.13.Final]
The error message says it all. findByDescription() is supposed to return 0 or 1 DocumentType, but it returns several ones. So either your Java design, or your data is corrupted. If you're really supposed to have a single document type with a given description, there should be a unique constraint in the database, that would prevent you from breaking that rule.
List<Item> findAllByOrderByModifiedAtDesc();
Item은 이렇게 함
앗 바본가 orderRepository에 이렇게 해놨음
당연히 하나밖에 리턴이 안되겠죠..
Optional <Order> findAllByItemId(Long itemId);
⛳해결 : Optional<Order> -> List<Order>로 수정함
💡개선 : List<Order>도 Optional로 감싸서 null일때 에러 throw하고 싶어짐
public List<OrderResponseDto> getOrders(Long itemId){
return orderRepository.findAllByItemId(itemId)
.stream()
.map(OrderResponseDto::new)
.collect(Collectors.toList());
}
근데 이것도 못찾거나 null일때 에러 리턴하고 싶은데…
Optional로 감싸봄
Optional<List<Order>> findAllByItemId(Long itemId);
여기는 이렇게 해봄
public List<OrderResponseDto> getOrders(Long itemId){
return orderRepository.findAllByItemId(itemId).orElseThrow(()-> new NullPointerException("해당 id로 주문요청을 찾을 수 없습니다."))
.stream()
.map(OrderResponseDto::new)
.collect(Collectors.toList());
}
잘 됨
🚩문제 : Order update기능 구현하고 수정할 request를 보내니까 백지가 뜸
Error도 안 잡힘
⛳해결 : 헤더에 Authorization안 넣은 거였어서 저거 넣어줌
🚩문제 : 이제 response는 오는데 db가 안 바뀜
"message": "구매 요청 업데이트 성공했습니다",
"data": {
"orderId": 5,
"buyerName": "닉2",
"address": "수정수정",
"price": "가격가격",
"orderStatus": "PENDING"
}
}
아 뭔가
Transaction안 달아놓은 거 같음
Service단의 Update함수에는 @Transactional
이걸 꼭 달아줘야 함
Q. 저걸 왜 달아줘야 하더라…
⛳ 해결 : Service의 update method에 @Transaction 달아주니까 잘 됐음
저거 달아주니까 이제 됐다
🎪하고싶은 것 : 로그인했을때/ 로그인 안 했을때 path는 같고 method명이랑 variable은 다르게 메서드들 오버로딩 하는 것!
Controller
@GetMapping("/read")
public ApiResponse<List<OrderResponseDto>> getOrdersForAll(
@RequestParam Long itemId
) {
try {
List<OrderResponseDto> responseDto = orderService.getOrders(itemId);
return new ApiResponse<List<OrderResponseDto>>(HttpStatus.OK.value(),"구매 요청 조회에 성공했습니다",responseDto);
}catch (RejectedExecutionException | NullPointerException ex){
return new ApiResponse<List<OrderResponseDto>>(HttpStatus.BAD_REQUEST.value(),ex.getMessage());
}
}
@GetMapping("/read")
public ApiResponse<List<OrderResponseDto>> getOrdersForItemAuthor(
@RequestParam Long itemId,
@AuthenticationPrincipal UserDetailsImpl userDetails
) {
try {
List<OrderResponseDto> responseDto = orderService.getOrdersForUsers(itemId, userDetails.getUser());
return new ApiResponse<List<OrderResponseDto>>(HttpStatus.OK.value(),"구매 요청 조회에 성공했습니다",responseDto);
}catch (RejectedExecutionException | NullPointerException ex){
return new ApiResponse<List<OrderResponseDto>>(HttpStatus.BAD_REQUEST.value(),ex.getMessage());
}
}
Service에서 아이템의 작성자면 order에 id랑 address출력해주고
아니면 저거 빼고 출력하는게 하고싶음
public List<OrderResponseDto> getOrdersForUsers(Long itemId, User user){
List<Order> orders = orderRepository.findAllByItemId(itemId).orElseThrow(()-> new NullPointerException("해당 id로 구매요청을 찾을 수 없습니다."));
if(orders.get(0).getItem().getSeller().equals(user.getSeller())){
return orders.stream()
.map(OrderResponseDto::new)
.collect(Collectors.toList());
}else {
}
}
🚩문제 : 근데 상황에 따라서 리턴 타입이 달라야됨
OrderResponseDto에는 orderid랑 address가 표시되고
저게 약간 바깥에 보여주기 싫은 정보나 개인정보일 수 있으니
PublicOrderResponseDto에는 orderid랑 address를 뺀 price랑 nickname이런것만 출력됨
상황에 따라서 리턴 타입이 다른걸 대체 어떻게 하냐 싶었음
⛳해결 : 그래서 데이터타입이 두개 있는 리턴 타입 클래스를 제너릭으로 만들어봄
package com.raincloud.sunlightmarket.global.dto;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class DoubleResponse<T,U> {
private T data1;
private U data2;
public DoubleResponse(T data1, U data2){
this.data1 = data1;
this.data2 = data2;
}
}
public DoubleResponse<List<OrderResponseDto>,List<PublicOrderResponseDto>> getOrdersForUsers(Long itemId, User user){
List<Order> orders = orderRepository.findAllByItemId(itemId).orElseThrow(()-> new NullPointerException("해당 id로 구매요청을 찾을 수 없습니다."));
List<OrderResponseDto> orderDtos = null;
List<PublicOrderResponseDto> publicOrderDtos = null;
if(orders.get(0).getItem().getSeller().equals(user.getSeller())){//Item의 작성자가 볼때는 orderId와 address가 포함된 response리턴
orderDtos = orders.stream()
.map(OrderResponseDto::new)
.collect(Collectors.toList());
}else {//Item의 작성자가 아닌 유저가 볼때는 orderId와 address가 제외된 response리턴
publicOrderDtos = orders.stream()
.map(PublicOrderResponseDto::new)
.collect(Collectors.toList());
}
return new DoubleResponse(orderDtos,publicOrderDtos);
}
Controller
@GetMapping("/read")
public ApiResponse<DoubleResponse<List<OrderResponseDto>,List<PublicOrderResponseDto>>> getOrdersForItemAuthor(
@RequestParam Long itemId,
@AuthenticationPrincipal UserDetailsImpl userDetails
) {
try {
DoubleResponse<List<OrderResponseDto>,List<PublicOrderResponseDto>> responseDto = orderService.getOrdersForUsers(itemId, userDetails.getUser());
return new ApiResponse<DoubleResponse<List<OrderResponseDto>,List<PublicOrderResponseDto>>>(HttpStatus.OK.value(),"구매 요청 조회에 성공했습니다",responseDto);
}catch (RejectedExecutionException | NullPointerException ex){
return new ApiResponse<DoubleResponse<List<OrderResponseDto>,List<PublicOrderResponseDto>>>(HttpStatus.BAD_REQUEST.value(),ex.getMessage());
}
}
기적의 3단 제너릭 ㅋㅋㅋㅋㅋ 넘 웃기다
🚩문제 : path 오버로딩이 안 됨
com.raincloud.sunlightmarket.order.controller.OrderController#getOrdersForItemAuthor(Long, UserDetailsImpl) to {GET [/api/orders/read]}: There is already 'orderController' bean method com.raincloud.sunlightmarket.order.controller.OrderController#getOrdersForAll(Long) mapped.
orderController에서 오류남 따흑
com.raincloud.sunlightmarket.order.controller.OrderController#getOrdersForAll(Long) to {GET [/api/orders/read]}: There is already 'orderController' bean method com.raincloud.sunlightmarket.order.controller.OrderController#getOrdersForUsers(Long, UserDetailsImpl) mapped.
path 오버로딩이 안되나봄…
method parameter가 Long으로 똑같아서 그런가…
다른 방식 한번 써봄
⛳해결 : 같은 path를 공유하는 다른 메소드의 parameter를 PathVariable로 바꿔봄
@GetMapping("/read")
public ApiResponse<List<OrderResponseDto>> getOrdersForAll(
@RequestParam Long itemId
) {
try {
List<OrderResponseDto> responseDto = orderService.getOrders(itemId);
return new ApiResponse<List<OrderResponseDto>>(HttpStatus.OK.value(),"구매 요청 조회에 성공했습니다",responseDto);
}catch (RejectedExecutionException | NullPointerException ex){
return new ApiResponse<List<OrderResponseDto>>(HttpStatus.BAD_REQUEST.value(),ex.getMessage());
}
}
→
@GetMapping("/read/{itenId}")
public ApiResponse<List<OrderResponseDto>> getOrdersForAll(
@PathVariable Long itemId
) {
try {
List<OrderResponseDto> responseDto = orderService.getOrders(itemId);
return new ApiResponse<List<OrderResponseDto>>(HttpStatus.OK.value(),"구매 요청 조회에 성공했습니다",responseDto);
}catch (RejectedExecutionException | NullPointerException ex){
return new ApiResponse<List<OrderResponseDto>>(HttpStatus.BAD_REQUEST.value(),ex.getMessage());
}
}
오… 이렇게는 오버로딩이 되나봄 문제없이 동작됨
Authentication은 parameter로 안 쳐주나봄…
근데 생각해보니 저러면 path가 걍 달라지잖아.. 오버로딩이라고 볼 수 없으니 되는듯
같은 path에다가는 두개의 함수를 달 수 없는걸까?
🚩문제 : Item글쓴이어도 orderId랑 address가 보이는 response가 리턴되지 않음
아무튼 유저 1로 로그인해서 아이템의 Order들을 읽어봄
"status": 200,
"message": "구매 요청 조회에 성공했습니다",
"data": {
"data1": null,
"data2": [
{
"buyerName": "닉",
"price": null,
"orderStatus": "PENDING"
},
{
"buyerName": "닉",
"price": null,
"orderStatus": "PENDING"
}
]
}
}
유저 2로 로그인해서 읽어봄
{
"status": 200,
"message": "구매 요청 조회에 성공했습니다",
"data": {
"data1": null,
"data2": [
{
"buyerName": "닉",
"price": null,
"orderStatus": "PENDING"
},
{
"buyerName": "닉",
"price": null,
"orderStatus": "PENDING"
}
]
}
}
똑같으면 안되는데…
아 read밑에다 놔두면 filter를 거쳐서 @AuthenticationPrincipal UserDetailsImpl userDetails 로 User 정보가 안 들어오기 때문에
그냥 public만 리턴되는 걸수도 있겠다…
WebSecurityConfig에서 /orders/read/**는 인증없이 다 지나가게 필터에 처리해뒀으니 path를 /read말고 다른걸로 바꿔봄
유저 1로 로그인해봄
{
"status": 200,
"message": "구매 요청 조회에 성공했습니다",
"data": {
"data1": null,
"data2": [
{
"buyerName": "닉",
"price": null,
"orderStatus": "PENDING"
},
{
"buyerName": "닉",
"price": null,
"orderStatus": "PENDING"
}
]
}
}
유저 2로 로그인해봄 안 됨
{
"status": 200,
"message": "구매 요청 조회에 성공했습니다",
"data": {
"data1": null,
"data2": [
{
"buyerName": "닉",
"price": null,
"orderStatus": "PENDING"
},
{
"buyerName": "닉",
"price": null,
"orderStatus": "PENDING"
}
]
}
}
⛳해결 : 해당 유저인지 판별할때 Object끼리 equals하지 않고 String끼리 equals하게 함
if(orders.get(0).getItem().getSeller().equals(user.getSeller()))
→
if(orders.get(0).getItem().getSeller().getId().equals(user.getSeller().getId()))
지금 보니 id가 아니라 seller로 비교하고 있었음
{
"status": 200,
"message": "구매 요청 조회에 성공했습니다",
"data": {
"data1": [
{
"orderId": 2,
"buyerName": "닉",
"address": "주소주소2",
"price": null,
"orderStatus": "PENDING"
},
{
"orderId": 3,
"buyerName": "닉",
"address": "주소주소2",
"price": null,
"orderStatus": "PENDING"
}
],
"data2": null
}
}
오 Seller대신 seller_id로 비교하니까 됨
filter로 거르지 않아도 로그인 정보 없어도 메소드 안에서 돌아가게 하는 법은 없는지 내일 알아보기로 함
'Bin > 개발일지' 카테고리의 다른 글
2023-12-11, Today I Learned (0) | 2023.12.11 |
---|---|
2023-12-08, Today I Learned (1) | 2023.12.08 |
2023-12-06, Today I Leanred (2) | 2023.12.06 |
2023-12-05, Today I Learned (0) | 2023.12.05 |
2023-12-04, Today I Learned (0) | 2023.12.04 |