Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#39 서비스 CompletableFuture 추가, 정적메소드네이밍 #40

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 11 additions & 11 deletions docker/db/mysql/init/init.sql
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,6 @@ select * from pv_goods;
select * from pv_item;
select * from pv_goods where goods_no =1;
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gradle ci 에서 걸려서 수정한 것으로 넘어가시면됩니다.


select * from od_order;
select * from od_order_dtl;
select * from od_order_deli;
select * from od_order_pay;
select * from od_order_goods;
select * from od_order_bene;

/* 주문자 관리 기본 정보 마스터 */
CREATE TABLE IF NOT EXISTS od_order(
order_no INT(11) NOT NULL AUTO_INCREMENT,
Expand All @@ -89,14 +82,14 @@ CREATE TABLE IF NOT EXISTS od_order(
cell_no VARCHAR(30) NOT NULL,
insert_dtime DATETIME DEFAULT now(),
update_dtime DATETIME DEFAULT now(),
CONSTRAINT od_ord_master_pk PRIMARY KEY(order_no),
CONSTRAINT od_ord_master_pk PRIMARY KEY(order_no)
);

/* 상품단위 주문 정보 */
CREATE TABLE IF NOT EXISTS od_order_dtl(
order_no INT(11) NOT NULL AUTO_INCREMENT,
order_step INT(11) NOT NULL AUTO_INCREMENT, /* 단계 주문/취소/반품/ */
order_status /*주문상태 결제대기 결제중 */
order_step VARCHAR(4) NOT NULL, /* 단계 주문/취소/반품/ */
order_status VARCHAR(4) NOT NULL, /*주문상태 결제대기 결제중 */
goods_no INT(11) NOT NULL,
goods_nm VARCHAR(30) NOT NULL,
item_no INT(11) NOT NULL,
Expand All @@ -113,8 +106,15 @@ CREATE TABLE IF NOT EXISTS od_order_dtl(
CONSTRAINT od_order_dtl_pk PRIMARY KEY(order_no),
foreign key (order_no) references od_order(order_no)
);

/*
select * from od_order;
select * from od_order_dtl;
select * from od_order_deli;
select * from od_order_pay;
select * from od_order_goods;
select * from od_order_bene;
drop table pv_item;
drop table pv_goods;commit;
*/
select count(*) over(), a.* from pv_goods a ;
select a.goods_nm ,b.item_nm,a.* from pv_goods a, pv_item b where a.goods_no = b.goods_no ;
Original file line number Diff line number Diff line change
Expand Up @@ -25,55 +25,46 @@ public class GoodsController {

@GetMapping(value = "/{goodsNo}")
public CompletableFuture<GoodsManagementResponse> findGoods(@PathVariable Long goodsNo) {

CompletableFuture<GoodsManagementResponse> goodsResponseFuture = CompletableFuture.supplyAsync(() -> {
log.error("findGoodsThread = {}", Thread.currentThread().getName());
GoodsManagement goodsManagement = goodsService.findByGoodsNo(goodsNo);
return GoodsManagementResponse.toResponseDto(goodsManagement);

}).thenApplyAsync( //callback
return goodsService.findByGoodsNo(goodsNo).thenApplyAsync(goodsManagement -> {
return GoodsManagementResponse.fromDto(goodsManagement);
}).thenApplyAsync(
(GoodsManagementResponse response) -> {
log.error("findGoods thenApplayAsync= {}", Thread.currentThread().getName());
response.updateSuccess("0000", "조회성공");
return response;
}
);

return goodsResponseFuture;
}

@PostMapping
@ResponseStatus(HttpStatus.CREATED)
public CompletableFuture<GoodsManagementResponse> registerGoods(@RequestBody @Valid GoodsManagementRequest goodsManagementRequest) throws ExecutionException, InterruptedException {

CompletableFuture<GoodsManagementResponse> goodsResponseFuture = CompletableFuture.supplyAsync(() -> {
log.error("goodsName = {}, registerGoodsThread = {}", goodsManagementRequest.getGoodsNm(), Thread.currentThread().getName()); //ForkJoinPool.commonPool-worker-1
return goodsService.save(goodsManagementRequest.toServiceDto()); //등록

}).thenApplyAsync(
//dto ->
CompletableFuture<GoodsManagementResponse> goodsResponseFuture = goodsService.save(goodsManagementRequest.toDto()).thenApplyAsync(
(goodsManagement) -> {
log.error("goodsName = {}, goodsNo = {}", goodsManagementRequest.getGoodsNm(), goodsManagement.getGoodsNo());
log.error("saveAfter goodsName = {}, goodsNo = {}", goodsManagement.getGoodsNm(), goodsManagement.getGoodsNo());
log.error("registerGoodsThread thenApplyAsync = {}", Thread.currentThread().getName()); //ForkJoinPool.commonPool-worker-1
GoodsManagementResponse response = GoodsManagementResponse.toResponseDto(goodsManagement);
GoodsManagementResponse response = GoodsManagementResponse.fromDto(goodsManagement);
response.updateSuccess("0000", "등록성공");
return response;
}
).thenApplyAsync(
(response) -> {
if("0000".equals(response.getResultCode())){
smsService.smsMessage(response.getGoodsNo()); //Cosmetics-Thread-Pool1
}
return response;
}
);

//등록에 성공하면 메세지를 보낸다고 가정
if ("0000".equals(goodsResponseFuture.get().getResultCode())) {
smsService.smsMessage(goodsResponseFuture.get().getGoodsNo()); //Cosmetics-Thread-Pool1
}
return goodsResponseFuture;
}


@DeleteMapping(value = "/{goodsNo}")
public GoodsManagementResponse deleteGoods(@PathVariable Long goodsNo) {
log.error("deleteGoods : {}", goodsNo);
GoodsManagement goodsManagement = goodsService.deleteByGoodsNo(goodsNo);
//dto -> responseDto
GoodsManagementResponse responseGoodsManagement = GoodsManagementResponse.toResponseDto(goodsManagement);
GoodsManagementResponse responseGoodsManagement = GoodsManagementResponse.fromDto(goodsManagement);
responseGoodsManagement.updateSuccess("0000", "삭제성공");
return responseGoodsManagement;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package com.cosmetics.config;

import com.cosmetics.api.exception.handler.CosmeticsAsyncExceptionHandler;
import com.cosmetics.api.exception.handler.CosmeticsExceptionHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
Expand Down Expand Up @@ -30,4 +33,8 @@ public Executor getAsyncExecutor() {
//상황에 따라 최소 스레드 수 최대 스레드 수 대기 큐의 크기를 조절해야하는데 그 상황이 어떤 상황에 따라 어떤 걸 보고 어떻게 지정해야할 지
//궁금합니다
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new CosmeticsAsyncExceptionHandler();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ private static GoodsManagementRequest requestGoods(int i) {
String url = "http://localhost:" + port + "/v1/goods/{goodsNo}";
ResponseEntity<GoodsManagementResponse> responseEntity = testRestTemplate.getForEntity(url, GoodsManagementResponse.class, goodsNo);
assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(responseEntity.getBody().getGoodsNm()).isEqualTo("닥터스킨");
assertThat(responseEntity.getBody().getGoodsNm()).isEqualTo("닥터스");
}

@DisplayName("상품 삭제")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public void validVendorTest() throws Exception {
.andDo(print())
.andExpect(jsonPath("errorCode").value("INVALID_PARAMETER"))
.andExpect(jsonPath("errorMessage").value("유효하지 않는 값입니다"))
.andExpect(jsonPath("$.fieldErrorList[0].field").value(anyOf(is("vendorNm"), is("postNo"))))
.andExpect(jsonPath("$.fieldErrorList[0].field").value(anyOf(is("vendorNm"), is("postNo"), is("addr"))))
.andExpect(jsonPath("$.fieldErrorList[0].message").value("must not be blank"));

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public GoodsManagement(Long goodsNo,
this.addImage = addImage;
}

public static GoodsManagement toDto(GoodsManagementEntity goodsManagementEntity) {
public static GoodsManagement fromEntity(GoodsManagementEntity goodsManagementEntity) {
return GoodsManagement.builder()
.goodsNo(goodsManagementEntity.getGoodsNo())
.goodsNm(goodsManagementEntity.getGoodsNm())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ public List<GoodsItemManagement> toGoodsItemManagementList(List<GoodsItemManagem
.map(GoodsItemManagement::new).collect(Collectors.toList());
}

public GoodsManagement toServiceDto() {
public GoodsManagement toDto() {
return GoodsManagement.builder()
.goodsNo(goodsNo)
.goodsNm(goodsNm)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
@NoArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
public class GoodsManagementResponse extends ResponseDto {

private Long goodsNo;
private String category;
private String goodsNm;
Expand Down Expand Up @@ -65,7 +64,7 @@ public GoodsManagementResponse(Long goodsNo,
this.addImage = addImage;
}

public static GoodsManagementResponse toResponseDto(GoodsManagement goodsManagent) {
public static GoodsManagementResponse fromDto(GoodsManagement goodsManagent) {
return GoodsManagementResponse.builder()
.goodsNo(goodsManagent.getGoodsNo())
.category(goodsManagent.getCategory())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@
import com.cosmetics.domain.goods.dto.GoodsManagement;
import com.cosmetics.domain.goods.entity.GoodsManagementEntity;
import com.cosmetics.domain.goods.repository.GoodsRepository;
import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.concurrent.CompletableFuture;

@Service
@Slf4j
Expand All @@ -16,30 +18,29 @@ public class GoodsService {
private final GoodsRepository goodsRepository;

@Transactional
//@Async //써야하나?
public GoodsManagement findByGoodsNo(Long goodsNo) {
log.error("GoodsService Thread = {}", Thread.currentThread().getName());
//여기도 비동기처리를해야하나?
GoodsManagementEntity goodsManagementEntity = goodsRepository.findByGoodsNo(goodsNo).orElseThrow(() -> new IllegalArgumentException("상품이 존재하지 않습니다."));
//entity -> dto
return GoodsManagement.toDto(goodsManagementEntity);
public CompletableFuture<GoodsManagement> findByGoodsNo(Long goodsNo) {
return CompletableFuture.supplyAsync(() -> {
log.error("GoodsService Thread = {}", Thread.currentThread().getName());
GoodsManagementEntity goodsManagementEntity = goodsRepository.findByGoodsNo(goodsNo).orElseThrow(() -> new IllegalArgumentException("상품이 존재하지 않습니다."));
return GoodsManagement.fromEntity(goodsManagementEntity);
});
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"failed to lazily initialize a collection of role: com.cosmetics.domain.goods.entity.GoodsManagementEntity.items: could not initialize proxy - no Session"
비동기 프로그래밍으로 바꾼 뒤 상품조회에서 오류가 발생하였습니다.


@Transactional
public GoodsManagement save(GoodsManagement goodsManagement) {
//Service단은 따로 작업을 안했는데 이게 맞을까요?
GoodsManagementEntity resultGoodsManagementEntity = goodsRepository.save(goodsManagement.toEntity());

//entity -> dto
return GoodsManagement.toDto(resultGoodsManagementEntity);
public CompletableFuture<GoodsManagement> save(GoodsManagement goodsManagement) {
CompletableFuture<GoodsManagement> goodsManageFuture = CompletableFuture.supplyAsync(() -> {
log.error("GoodsService Thread = {}", Thread.currentThread().getName());
GoodsManagementEntity resultGoodsManagementEntity = goodsRepository.save(goodsManagement.toEntity());
return GoodsManagement.fromEntity(resultGoodsManagementEntity);
});
return goodsManageFuture;
}

@Transactional
public GoodsManagement deleteByGoodsNo(Long goodsNo) {
GoodsManagementEntity goodsManagementEntity = goodsRepository.findByGoodsNo(goodsNo).orElseThrow(() -> new IllegalArgumentException("상품이 존재하지 않습니다."));
long deleteCnt = goodsRepository.deleteByGoodsNo(goodsNo);

//entity -> dto
return GoodsManagement.toDto(goodsManagementEntity);
return GoodsManagement.fromEntity(goodsManagementEntity);
}
}
Loading