<!-- 애드몹 인증 --><dependency><groupId>com.google.crypto.tink</groupId><artifactId>apps-rewardedads</artifactId><version>1.7.0</version></dependency><dependency><groupId>joda-time</groupId><artifactId>joda-time</artifactId><version>2.10.10</version></dependency><dependency><groupId>com.google.code.gson</groupId><artifactId>gson</artifactId><version>2.8.9</version></dependency>
## 전역 설정
spring.jpa.properties.javax.persistence.query.timeout=5000
//
## DB config 별 설정이 나눠져 있다면
a.jpa.properties.javax.persistence.query.timeout=4000
@ConfigurationProperties(prefix = "a.jpa")
public static class AJpaProperties {
private Map<String, String> properties = new HashMap<>();
public Map<String, String> getProperties() {
return properties;
}
public void setProperties(Map<String, String> properties) {
this.properties = properties;
}
}
// or //
Map<String,Object> properties = new HashMap();
properties.put("javax.persistence.query.timeout", 5000);
EntityManager entityManager = entityManagerFactory.createEntityManager(properties);
//쿼리 별 설정//전역 설정이 있어도 override됨@Lock(LockModeType.PESSIMISTIC_WRITE)@Query("SELECT c FROM MoneyExchange c WHERE c.pk = :pk")@QueryHints({@QueryHint(name = "javax.persistence.lock.timeout", value = "6000")})MoneyExchange findOneWithLock(@Param("pk") MoneyExchange.PK pk);
설정 후 로그, local timeout(6초)를 따른다.
2023-01-05 13:22:07 DEBUG [s.t.s.AbstractPlatformTransactionManager.handleExistingTransa: 470][http-nio-8600-exec-2] Participating in existing transaction
select
from
hd_moneyexchange moneyexcha0_
wherefor update
2023-01-05 13:22:12 WARN [com.zaxxer.hikari.pool.ProxyConnection .checkException : 182][http-nio-8600-exec-2] HikariPool-1 - Connection com.mysql.cj.jdbc.ConnectionImpl@23ae77d9 marked as broken because of SQLSTATE(null), ErrorCode(0)
com.mysql.cj.jdbc.exceptions.MySQLTimeoutException: Statement cancelled due to timeout or client request
참고) queryHint에 다른 옵션들도 있을까 싶어서 아래 옵션을 주었으나 무시되었다. 아직까지도 지원을 하지 않는 모양
@QueryHints({@QueryHint(name = "javax.persistence.lock.scope", value = "EXTENDED")})
..
[http-nio-8600-exec-1] HHH000121: Ignoring unrecognized query hint [javax.persistence.lock.scope]
참고) spring-jpa lock option종류
LockModeType.PESSIMISTIC_WRITE 일반적인 옵션. 데이터베이스에 쓰기 락 다른 트랜잭션에서 읽기도 쓰기도 못함. (배타적 잠금)
LockModeType.PESSIMISTIC_READ 반복 읽기만 하고 수정하지 않는 용도로 락을 걸 때 사용 다른 트랜잭션에서 읽기는 가능함. (공유 잠금)
LockModeType.PESSINISTIC_FORCE_INCREMENT Version 정보를 사용하는 비관적 락
Hibernate: //저장1;
select
from
hd_user_notice usernotice0_
where
...
2023-01-05 10:15:04 WARN [c.n.g.s.m.MoneyExchangeService .saveDailyMoneyExchan: 394][http-nio-8600-exec-2] > saveDailyMoneyExchangeLog tx name: com.MoneyExchangeService.depositWithCredential
2023-01-05 10:15:04 DEBUG [o.s.orm.jpa.JpaTransactionManager .doGetTransaction : 375][http-nio-8600-exec-2] Found thread-bound EntityManager [SessionImpl(1213852261<open>)] for JPA transaction
2023-01-05 10:15:04 DEBUG [s.t.s.AbstractPlatformTransactionManager.handleExistingTransa: 470][http-nio-8600-exec-2] Participating in existing transaction
Hibernate: //저장3; 부모 transaction
insert
into
hd_moneyexchange_log
values
2023-01-05 10:15:04 WARN [c.n.g.s.m.MoneyExchangeService .saveDailyMoneyExchan: 397][http-nio-8600-exec-2] > saveDailyMoneyExchangeLog tx name: com.MoneyExchangeService.depositWithCredential
>> before withdraw
2023-01-05 10:15:04 WARN [c.n.g.s.m.MoneyExchangeService .lambda$depositWithCr: 253][http-nio-8600-exec-2] > before throw tx name: com.MoneyExchangeService.depositWithCredential
...
2023-01-05 10:15:04 DEBUG [o.s.orm.jpa.JpaTransactionManager .doGetTransaction : 375][http-nio-8600-exec-2] Found thread-bound EntityManager [SessionImpl(157605982<open>)] for JPA transaction
2023-01-05 10:15:04 DEBUG [s.t.s.AbstractPlatformTransactionManager.handleExistingTransa: 429][http-nio-8600-exec-2] Suspending current transaction, creating new transaction with name [com.MoneyExchangeLogEntityService.logFromNewTransaction]
2023-01-05 10:15:04 DEBUG [o.s.orm.jpa.JpaTransactionManager .doBegin : 412][http-nio-8600-exec-2] Opened new EntityManager [SessionImpl(251535742<open>)] for JPA transaction
2023-01-05 10:15:04 DEBUG [o.s.orm.jpa.JpaTransactionManager .doBegin : 440][http-nio-8600-exec-2] Exposing JPA transaction as JDBC [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle@1bd03ae5]
2023-01-05 10:15:04 DEBUG [o.s.orm.jpa.JpaTransactionManager .doGetTransaction : 375][http-nio-8600-exec-2] Found thread-bound EntityManager [SessionImpl(1213852261<open>)] for JPA transaction
2023-01-05 10:15:04 DEBUG [s.t.s.AbstractPlatformTransactionManager.handleExistingTransa: 429][http-nio-8600-exec-2] Suspending current transaction, creating new transaction with name [com.MoneyExchangeLogEntityService.logFromNewTransaction]
2023-01-05 10:15:04 DEBUG [o.s.orm.jpa.JpaTransactionManager .doBegin : 412][http-nio-8600-exec-2] Opened new EntityManager [SessionImpl(830560897<open>)] for JPA transaction
2023-01-05 10:15:04 DEBUG [o.s.orm.jpa.JpaTransactionManager .doBegin : 440][http-nio-8600-exec-2] Exposing JPA transaction as JDBC [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle@1afe4eee]
2023-01-05 10:15:04 DEBUG [o.s.orm.jpa.JpaTransactionManager .doGetTransaction : 375][http-nio-8600-exec-2] Found thread-bound EntityManager [SessionImpl(2044396758<open>)] for JPA transaction
2023-01-05 10:15:04 DEBUG [s.t.s.AbstractPlatformTransactionManager.handleExistingTransa: 429][http-nio-8600-exec-2] Suspending current transaction, creating new transaction with name [com.MoneyExchangeLogEntityService.logFromNewTransaction]
2023-01-05 10:15:04 DEBUG [o.s.orm.jpa.JpaTransactionManager .doBegin : 412][http-nio-8600-exec-2] Opened new EntityManager [SessionImpl(1710520606<open>)] for JPA transaction
2023-01-05 10:15:04 DEBUG [o.s.orm.jpa.JpaTransactionManager .doBegin : 440][http-nio-8600-exec-2] Exposing JPA transaction as JDBC [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle@7f696057]
2023-01-05 10:15:04 WARN [c.n.g.s.MoneyExchangeLogEntityService .logFromNewTransactio: 22][http-nio-8600-exec-2] > error logFromNewTransaction tx name: com.MoneyExchangeLogEntityService.logFromNewTransaction
2023-01-05 10:15:04 DEBUG [o.s.orm.jpa.JpaTransactionManager .doGetTransaction : 375][http-nio-8600-exec-2] Found thread-bound EntityManager [SessionImpl(830560897<open>)] for JPA transaction
2023-01-05 10:15:04 DEBUG [s.t.s.AbstractPlatformTransactionManager.handleExistingTransa: 470][http-nio-8600-exec-2] Participating in existing transaction
Hibernate: //에러 로그 삽입
insert
into
hd_moneyexchange_log
values
2023-01-05 10:15:04 DEBUG [s.t.s.AbstractPlatformTransactionManager.processCommit : 740][http-nio-8600-exec-2] Initiating transaction commit
2023-01-05 10:15:04 DEBUG [o.s.orm.jpa.JpaTransactionManager .doCommit : 557][http-nio-8600-exec-2] Committing JPA transaction on EntityManager [SessionImpl(1710520606<open>)]
2023-01-05 10:15:04 DEBUG [o.s.orm.jpa.JpaTransactionManager .doCleanupAfterComple: 648][http-nio-8600-exec-2] Closing JPA EntityManager [SessionImpl(1710520606<open>)] after transaction
2023-01-05 10:15:04 DEBUG [s.t.s.AbstractPlatformTransactionManager.cleanupAfterCompleti: 996][http-nio-8600-exec-2] Resuming suspended transaction after completion of inner transaction
2023-01-05 10:15:04 DEBUG [s.t.s.AbstractPlatformTransactionManager.processCommit : 740][http-nio-8600-exec-2] Initiating transaction commit
2023-01-05 10:15:04 DEBUG [o.s.orm.jpa.JpaTransactionManager .doCommit : 557][http-nio-8600-exec-2] Committing JPA transaction on EntityManager [SessionImpl(830560897<open>)]
2023-01-05 10:15:04 DEBUG [o.s.orm.jpa.JpaTransactionManager .doCleanupAfterComple: 648][http-nio-8600-exec-2] Closing JPA EntityManager [SessionImpl(830560897<open>)] after transaction
2023-01-05 10:15:04 DEBUG [s.t.s.AbstractPlatformTransactionManager.cleanupAfterCompleti: 996][http-nio-8600-exec-2] Resuming suspended transaction after completion of inner transaction
2023-01-05 10:15:04 DEBUG [s.t.s.AbstractPlatformTransactionManager.processCommit : 740][http-nio-8600-exec-2] Initiating transaction commit
2023-01-05 10:15:04 DEBUG [o.s.orm.jpa.JpaTransactionManager .doCommit : 557][http-nio-8600-exec-2] Committing JPA transaction on EntityManager [SessionImpl(251535742<open>)]
2023-01-05 10:15:04 DEBUG [o.s.orm.jpa.JpaTransactionManager .doCleanupAfterComple: 648][http-nio-8600-exec-2] Closing JPA EntityManager [SessionImpl(251535742<open>)] after transaction
2023-01-05 10:15:04 DEBUG [s.t.s.AbstractPlatformTransactionManager.cleanupAfterCompleti: 996][http-nio-8600-exec-2] Resuming suspended transaction after completion of inner transaction
2023-01-05 10:15:06 DEBUG [s.t.s.AbstractPlatformTransactionManager.processRollback : 833][http-nio-8600-exec-2] Initiating transaction rollback
2023-01-05 10:15:06 DEBUG [o.s.orm.jpa.JpaTransactionManager .doRollback : 583][http-nio-8600-exec-2] Rolling back JPA transaction on EntityManager [SessionImpl(2044396758<open>)]
2023-01-05 10:15:06 DEBUG [o.s.orm.jpa.JpaTransactionManager .doCleanupAfterComple: 648][http-nio-8600-exec-2] Closing JPA EntityManager [SessionImpl(2044396758<open>)] after transaction
2023-01-05 10:15:06 DEBUG [s.t.s.AbstractPlatformTransactionManager.cleanupAfterCompleti: 996][http-nio-8600-exec-2] Resuming suspended transaction after completion of inner transaction
2023-01-05 10:15:06 DEBUG [s.t.s.AbstractPlatformTransactionManager.processRollback : 833][http-nio-8600-exec-2] Initiating transaction rollback
2023-01-05 10:15:06 DEBUG [o.s.orm.jpa.JpaTransactionManager .doRollback : 583][http-nio-8600-exec-2] Rolling back JPA transaction on EntityManager [SessionImpl(1213852261<open>)]
2023-01-05 10:15:06 DEBUG [o.s.orm.jpa.JpaTransactionManager .doCleanupAfterComple: 648][http-nio-8600-exec-2] Closing JPA EntityManager [SessionImpl(1213852261<open>)] after transaction
2023-01-05 10:15:06 DEBUG [s.t.s.AbstractPlatformTransactionManager.cleanupAfterCompleti: 996][http-nio-8600-exec-2] Resuming suspended transaction after completion of inner transaction
2023-01-05 10:15:06 DEBUG [s.t.s.AbstractPlatformTransactionManager.processRollback : 833][http-nio-8600-exec-2] Initiating transaction rollback
2023-01-05 10:15:06 DEBUG [o.s.orm.jpa.JpaTransactionManager .doRollback : 583][http-nio-8600-exec-2] Rolling back JPA transaction on EntityManager [SessionImpl(157605982<open>)]
2023-01-05 10:15:06 DEBUG [o.s.orm.jpa.JpaTransactionManager .doCleanupAfterComple: 648][http-nio-8600-exec-2] Closing JPA EntityManager [SessionImpl(157605982<open>)] after transaction
2023-01-05 10:15:06 DEBUG [s.t.s.AbstractPlatformTransactionManager.cleanupAfterCompleti: 996][http-nio-8600-exec-2] Resuming suspended transaction after completion of inner transaction
2023-01-05 10:15:06 DEBUG [.m.m.a.ExceptionHandlerExceptionResolver.doResolveHandlerMeth: 416][http-nio-8600-exec-2] Using @ExceptionHandler
privatevoidrunAndSaveErrorLogIfFail(MoneyExchangeRequest request, long availableMoney, Runnable runnable){
runnable을 받는 함수는 처음 봐서 특이점이 있나 싶었는데, 원작자에게 물어보니 try-catch 에러로그 부분을 다양한 곳에서 공통으로 쓰려고 하셨다고 한다. 즉, logic 함수만 갈아 끼고 error발생 시 처리하는 부분을 공통화하기 위한 로직이었다. 예전 pr때 catch부분이 너무 똑같고 많이 반복된다는 지적이 있었는데 그걸 보완하기 위한 코드인 듯. 멀티스레드나 그런 걸 위한 건 아니다.
로그를 보면서 코드를 분석해 본다.
저장 1에 대한 select 실행
저장 2에 hibernate로그는 없음
saves 함수의 저장 3번(saveDailyMoneyExchangeLog) 로직이 실행되고(엄마 transaction)
이 부분이 왜 실행되는지 모르겠다. saves 함수를 나온 것도 아니고, throw 전의 로그를 찍기도 전에 insert 로그가 찍힌다. 물론 나중에 롤백되긴 하는데.. 다른 insert문은 하나도 안 찍히고 마지막 거만 찍히는 게 이해가 잘 안 가는 부분.
saves를 나오고 throw를 만나서 새로운 transaction이 열림(자식 transaction시작; creating new transaction with name logFromNewTransaction)
transatcion manager가 chained 여서 transaction이 세 번 열림..
에러 로그를 insert 하고 commit 하고 엄마 transaction에게 돌아가고
엄마 transaction은 exception을 전파받아 doRollback을 세 번(엄마 transaction자체가 chained transaction) 실행
그리고 마지막으로 exception은 @ExceptionHandler를 타고 최종 전파된다.
throw를 지우고 성공 시 로그
Hibernate: //저장1;
select
from
hd_user_notice usernotice0_
where
...
2023-01-05 14:07:36 WARN [c.n.g.s.m.MoneyExchangeService .saveDailyMoneyExchan: 396][http-nio-8600-exec-1] > saveDailyMoneyExchangeLog tx name: com.MoneyExchangeService.depositWithCredential
2023-01-05 14:07:36 DEBUG [o.s.orm.jpa.JpaTransactionManager .doGetTransaction : 375][http-nio-8600-exec-1] Found thread-bound EntityManager [SessionImpl(425779152<open>)] for JPA transaction
2023-01-05 14:07:36 DEBUG [s.t.s.AbstractPlatformTransactionManager.handleExistingTransa: 470][http-nio-8600-exec-1] Participating in existing transaction
Hibernate: //저장3 쿼리 실행
insert
into
hd_moneyexchange_log
values
#### saves 함수 밖...
2023-01-05 14:07:36 WARN [c.n.g.s.m.MoneyExchangeService .lambda$depositWithCr: 256][http-nio-8600-exec-1] > before throw tx name: com.MoneyExchangeService.depositWithCredential
##static close
2023-01-05 14:07:36 DEBUG [s.t.s.AbstractPlatformTransactionManager.processCommit : 740][http-nio-8600-exec-1] Initiating transaction commit
2023-01-05 14:07:36 DEBUG [o.s.orm.jpa.JpaTransactionManager .doCommit : 557][http-nio-8600-exec-1] Committing JPA transaction on EntityManager [SessionImpl(1732642577<open>)]
2023-01-05 14:07:36 DEBUG [o.s.orm.jpa.JpaTransactionManager .doCleanupAfterComple: 648][http-nio-8600-exec-1] Closing JPA EntityManager [SessionImpl(1732642577<open>)] after transaction
2023-01-05 14:07:36 DEBUG [s.t.s.AbstractPlatformTransactionManager.cleanupAfterCompleti: 996][http-nio-8600-exec-1] Resuming suspended transaction after completion of inner transaction
##log close
2023-01-05 14:07:36 DEBUG [s.t.s.AbstractPlatformTransactionManager.processCommit : 740][http-nio-8600-exec-1] Initiating transaction commit
2023-01-05 14:07:36 DEBUG [o.s.orm.jpa.JpaTransactionManager .doCommit : 557][http-nio-8600-exec-1] Committing JPA transaction on EntityManager [SessionImpl(425779152<open>)]
2023-01-05 14:07:36 DEBUG [o.s.orm.jpa.JpaTransactionManager .doCleanupAfterComple: 648][http-nio-8600-exec-1] Closing JPA EntityManager [SessionImpl(425779152<open>)] after transaction
2023-01-05 14:07:36 DEBUG [s.t.s.AbstractPlatformTransactionManager.cleanupAfterCompleti: 996][http-nio-8600-exec-1] Resuming suspended transaction after completion of inner transaction
## user close
2023-01-05 14:07:36 DEBUG [s.t.s.AbstractPlatformTransactionManager.processCommit : 740][http-nio-8600-exec-1] Initiating transaction commit
2023-01-05 14:07:36 DEBUG [o.s.orm.jpa.JpaTransactionManager .doCommit : 557][http-nio-8600-exec-1] Committing JPA transaction on EntityManager [SessionImpl(1465294398<open>)]
Hibernate: //저장1 쿼리 실행
insert
into
hd_user_notice
values
Hibernate:
update //저장2 쿼리 실행
hd_moneyexchange
setwhere
2023-01-05 14:07:36 DEBUG [o.s.orm.jpa.JpaTransactionManager .doCleanupAfterComple: 648][http-nio-8600-exec-1] Closing JPA EntityManager [SessionImpl(1465294398<open>)] after transaction
2023-01-05 14:07:36 DEBUG [s.t.s.AbstractPlatformTransactionManager.cleanupAfterCompleti: 996][http-nio-8600-exec-1] Resuming suspended transaction after completion of inner transaction
디버그를 걸고 보니 위 원인을 알 수 있었다.
save 함수 구현체에 있는 isNew부분이 포인트다.
isNew()메서드는 새로운Entity를 판단하기 위해 ID값을 확인하는데 기본 전략은 아래와 같다.
ID의 타입이 객체 타입(reference; string) 일 때:null
ID의 타입이 기본 타입(primitive) 일 때:0
merge vs persist?
merge는 Detached 상태의 Entity를 다시 영속화 하는데 사용되고 persist는 최초 생성된 Entity를 영속화 하는데 사용된다.
Merge : Detached Entity ⇒ Managed Entity
Persist : New Entity ⇒ Managed Entity
em.merge() is trying to retrieve an existing entity from DB with a SELECT query and update it. So if the entity was never persisted, this will waste some CPU cycles. On the other side em.persist() will only produce one INSERT query.
참고로 entity가 persisted, 즉 영속된 entity인지는 EntityManager안의 contains함수를 통해 알 수 있다.
em.contains(entity)
저장 1
pk(객체 타입) is not null -> merge -> 영속성 없음, select 조회, 영속성 부여 -> 조회 결과가 없으니 후에 insert 예약 -> seq가 null로 인서트 예정이었으나 DB에서 넣어줌 -> 트랜젝션 종료쯤 commit시 날아감
저장 2
자식 transaction으로 save한 결과의 entity를 넘겨 받음 -> pk(객체 타입) is not null -> merge -> em.contains(entity) == true-> 영속성 있음, 추가 select 없음 -> dirty checking, 수정된거 확인 후에 update 예약 -> 트랜젝션 종료쯤 commit시 날아감
저장 3
key가 auto increment로 생성되는 seq(Long) 값이고 최초에는 null. -> persist -> id(seq)값을 가져오기 위해 insert를 쏴서 얻음
>> 그래서 중간에 insert 쿼리가 뜬금없이 날아감
그리고 저장 3의 persist 된 엔티티는 후에 수정된 사항이 없어서 추가 insert문이 안 날아간다.
save 호출 후 엔티티를 사용할 일이 있다면(추가 수정건 등) 영속상태의 엔티티를 반환받아서 사용하는 게 성능에 좋다(추가 select문이 안 날아간다).
참고) chained transaction manager
현재 chained transaction manager 설정이 아래와 같고저장 1은USER,저장 2도USER,저장 3은LOG transaction manager에 속한다.
transaction USER begin
transaction LOG begin
transaction STATIC begin
transaction STATIC commit
transaction LOG commit -> error rollbacks LOG, USER
transaction USER commit -> error, only rollbacks USER
지정된 순서대로 트랜잭션이 실행되고, 지정된 역순으로 트랜잭션이 종료된다. 다시 말해, 에러를 내기 쉬운 트랜잭션을 마지막에 지정해서 트랜잭션 종료 작업이 최초로 호출되도록 해야 한다 왜냐면 에러를 낼 가능성이 높은 트랜잭션이 최초로 롤백이 돼야 그 뒤의 다른 트랜잭션도 따라서 롤백되기 때문이다. ChainedTransactionManager는 단지 트랜잭션 시작과 종료를 동시에 해줄 뿐이지 Two Phase Commit을 지원하는 게 아니라서 이미 다른 트랜잭션이 커밋된 상황에서 하나의 트랜잭션이 롤백 됐다고 해서 이미 커밋된 것들이 다시 롤백되지는 않는다. 따라서 가장 위험한 요소를 최초로 커밋/롤백 시도 하도록 해야 한다.
GET api를 브라우저나 포스트맨으로 api를 쐈을 때는 잘 나오는데, webClient나 curl로 쏘면 아래와 같이 안 나오는 경우가 있다.
<html><head><title>301 Moved Permanently</title></head><body><center><h1>301 Moved Permanently</h1></center><hr><center>nginx/1.18.0</center></body></html>
테스트해 보니 url에 https:// 를 안 붙이면 나는 듯하다.
보통은 이렇게 해결하면 되지만 애초에 ssl 설정이 안 되어 있는 곳이 있다.
추가적인 옵션를 주는 방법이 있지 않을까 해서 살펴본다.
curl은 -L 옵션을 주면 아래와 같이 자동 redirect를 해서 결과가 나오는 것을 볼 수 있다.
-L, --location (HTTP/HTTPS) If the server reports that the requested page has moved to a different location (indicated with a Location: header and a 3XX response code), this option will make curl redo the request on the new place. If used together with -i, --include or -I, --head, headers from all requested pages will be shown. When authentication is used, curl only sends its credentials to the initial host. If a redirect takes curl to a different host, it won't be able to intercept the user+password. See also --location-trusted on how to change this. You can limit the amount of redirects to follow by using the --max-redirs option.
When curl follows a redirect and the request is not a plain GET (for example POST or PUT), it will do the following request with a GET if the HTTP response was 301, 302, or 303. If the response code was any other 3xx code, curl will re-send the following request using the same unmodified method.
curl -L -v 'dev.com/api/external/money-exchange/configuration?exchangeGameType=&sync=false'
* Trying 10....
* TCP_NODELAY set
* Connected to dev.com (10..) port 80 (#0)
> GET /api/external/money-exchange/configuration?exchangeGameType=&sync=false HTTP/1.1
> Host: dev.com
> User-Agent: curl/7.64.1
> Accept: */*
>
< HTTP/1.1 301 Moved Permanently
< Server: nginx/1.18.0
< Date: Tue, 03 Jan 2023 01:05:17 GMT
< Content-Type: text/html
< Content-Length: 169
< Connection: keep-alive
< Location: https://dev.com/api/external/money-exchange/configuration?exchangeGameType=&sync=false
<
* Ignoring the response-body
* Connection #0 to host dev.com left intact
* Issue another request to this URL: 'https://dev.com/api/external/money-exchange/configuration?exchangeGameType=&sync=false'
* Trying 10...
* TCP_NODELAY set
* Connected to dev.com (10.) port 443 (#1)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: /etc/ssl/cert.pem
CApath: none
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
* ALPN, server accepted to use http/1.1
* Server certificate:
* subject: C=KR; ST=Gyeonggi-do; O=N Corporation; CN=*..com
* start date: Dec 21 00:00:00 2022 GMT
* expire date: Jan 21 23:59:59 2024 GMT
* subjectAltName: host "dev.com" matched cert's "*..com"
* issuer: C=GB; ST=Greater Manchester; L=Salford; O=Sectigo Limited; CN=Sectigo RSA Organization Validation Secure Server CA
* SSL certificate verify ok.
> GET /api/external/money-exchange/configuration?exchangeGameType=&sync=false HTTP/1.1
> Host: dev.com
> User-Agent: curl/7.64.1
> Accept: */*
>
< HTTP/1.1 200
< Server: nginx/1.18.0
< Date: Tue, 03 Jan 2023 01:05:17 GMT
< Content-Type: application/json
< Transfer-Encoding: chunked
< Connection: keep-alive
<
* Connection #1 to host dev.com left intact
{"header":{"status":200,"message":"OK","isSuccessful":true},"result":{}}}
* Closing connection 0
* Closing connection 1
curl도 -L 옵션을 주면 되니, webclient도 관련 옵션이 있을 것 같아 찾아보았는데..
public Data(Long user, Long count, Long money, Long fee, MoneyExchangeLogType type) {
this.user = user;
this.count = count;
this.money = money;
this.fee = fee;
this.type = type;
}
그런데 logType을 추가하기 전에는 잘 되던 게, 이거 하나 추가했다고 서버가 안 뜨는 것이다.. (띠용)
Unable to locate appropriate constructor on class [com.event.moneyexchange.MoneyExchangeAllResponse$Data]. Expectedargumentsare: long, long, long, long
[cause=org.hibernate.PropertyNotFoundException: no appropriate constructor in class: com.event.moneyexchange.MoneyExchangeAllResponse$Data]
아무리 구글링해도 정확히 해결한 사람을 보기가 힘들어
constructor로 받아올 때는 결과 값이 아닌 값들은 자동 생략(omit)되는 가보다 하고 넘어가긴 했다.
@Query에서 dto로 바로 받을 수 있는데, 이 때 .으로 inner class를 표시하면 아래와 같이 에러가 난다.
java.lang.IllegalArgumentException: org.hibernate.QueryException: could not instantiate class
static inner class를 지칭할 때는 . 이 아닌 $로 해야한다.
public classMoneyExchangeAllResponse{
private Data total;
@Getter
@Setter
public staticclassData{
private Long user;
private Long count;
private Long money;
private Long fee;
public Data(Long user, Long count, Long money, Long fee) {
this.user = user;
this.count = count;
this.money = money;
this.fee = fee;
}
}
}
@Query(value = "select new com.event.moneyexchange.MoneyExchangeAllResponse$Data( "")
...