이것도 꽤 고생했다

 

프로젝트 크기가 커지면서 테스트케이스들이 많아지고 어느순간부터 OOM 발생 ..

 

여러 문서들에서는 

gradle.properties에서는 아래와 같은 형태로 메모리를 늘리면 된다

org.gradle.jvmargs=-Xmx2g

 

라고하는데

나의 경우는 제대로 잘 동작하지 않았다 <- 사실 이 문제를 아는데까지가 굉장히 오래걸렸음

 

결론부터 말하면 gradle.properties는 gradle daemon과 관련된 설정이다

아래 jps -lv 명령어를 사용하면 실제로 org.gradle.launcher.daemon.bootstrap.GradleDaemon <- 이놈들의 heap size 설정만 변경된것을 확인할 수 있다

jps -lv

2634 org.gradle.launcher.daemon.bootstrap.GradleDaemon ... -Xmx2g
16186 org.gradle.launcher.GradleMain ... -Xmx64m -Xms64m 
13051 org.gradle.launcher.daemon.bootstrap.GradleDaemon ... -Xmx2g
16271 worker.org.gradle.process.internal.worker.GradleWorkerMain -Xmx512m
...

 

하지만 실제 build를 수행하는애들은 worker인게 문제!!!

 

실제로 문서에는 아래와 같이 되어있다

https://docs.gradle.org/current/userguide/upgrading_version_4.html#rel5.0:default_memory_settings

All workers, including compilers and test executors, now start with 512MB of heap. The previous default was 1/4th of physical memory. Large projects may have to increase this setting on the relevant tasks, e.g. JavaCompile or Test

나랑 비슷한 질문을 한 사람도 있다 https://github.com/gradle/gradle/issues/8166

 

Default xmx changed before and after 5.0 for test executor? · Issue #8166 · gradle/gradle

When upgrading gradle from 4.10.2 to 5.1 (only variable, no other plugin changes), we observed some tests failing due to OOM in 5.1 which passed in 4.10.2 without any issue. With further investigat...

github.com

 

 

따라서 build.gradle에는 아래와 같은 스크립트가 추가되어야한다

test {
  maxHeapSize = "1024m" //원하는 만큼 변경
}

위에서 설정한 heapSize가 실제로 gradle build 명령어에서 사용하는 heap size를 수정하게 해준다!

 

멀티프로젝트라면 아래와 같이 하면 된다

subprojects {
  test {
    maxHeapSize = "1024m" //원하는 만큼 변경
  }
  
  ...
}

 

쩝 ..써놓고 보니까 별거없어보임 ㅠ

 

 

아... 2시간정도를 날렸다

 

spring pageable의 경우 기본적으로 page, size라는 파라미터를 받아서 페이징을 조금 더 쉽게 구현할 수 있도록 해주는데

page,size라는 이름이 고정값이라 변경이 필요했다.

 

다음과 같이 yml파일에서 spring.data.web.pageable.size-parameter 값으로 설정해주면 된다

라는 블로그를 많이 찾아봤지만 실제로는 되지 않았고 엉뚱한곳만 보다가 해결했다.

 

결론부터 말하면 우리가 설정해야 하는 값은 spring.data.rest.limit-parameter

설정문제겠지만 spring.data.web.pageable.size-parameter 이 동작하지 않았다면 실제 스프링 빈에 등록되는 애는 HateoasPageableHandlerMethodArgumentResolver 일 확률이 매우 높다.

 

HateoasPageableHandlerMethodArgumentResolver는 PageableHandlerMethodArgumentResolver의 하위타입이다

 

따라서 PageableHandlerMethodArgumentResolver.setSizeParameterName() 메서드를 단순히 호출하면 안되고RepositoryRestMvcConfiguration 클래스 내부에 있는 pageableResolver() 메서드로 한번 감싸진 HateoasPageableHandlerMethodArgumentResolver를 리턴하도록 해야한다.

 

 

암튼 결론은

spring.data.web.pageable.size-parameter 가 안된다면

spring.data.rest.limit-parameter 사용하기

 

오랜만쓰 ... 

 

break 잡고 디버깅모드로 돌리는데 ide가 급격히 느려질때는

 

자신이 코드에 Method Breakpoint를 잡았는지, Line Breakpoint를 잡았는지 확인할 것.

 

맥 기준으로 Shift + Command + F8 을 누르면 ide에 적용된 모든 breakpoint를 확인할 수 있는데

 

만약 Java Method Breakpoints에 브레이크가 걸려있다면 Line Breakpoint로 바꾸면 매우 빨라짐!!

 

 

 

https://intellij-support.jetbrains.com/hc/en-us/articles/206544799

 

Java: slow performance or hangups when starting debugger and stepping

Debugger performance can be affected by the following: Method breakpoints will slow down debugger a lot because of the JVM design, they are expensive to evaluate. Remove method breakpoints and co...

intellij-support.jetbrains.com

 

비슷한 내용으로 검색하면 많은 글들에서 /etc/security/limits.conf 를 수정하라는 글들이 있었는데

 

※급하게 테스트가 필요할 경우!

 

ES 7.x 버전에서 아래와 같이 해결했다.

 

 

 

elasticsearch.yml에 아래내용 참고해서 추가

network.host: 0.0.0.0
http.port: 9200
transport.host: localhost
transport.tcp.port: 9300

 

transport.host, transport.tcp.port를 추가해서 다시 재기동하니까 잘 됐다.

 

 

 

 

 

stackoverflow.com/questions/46771233/max-file-descriptors-for-elasticsearch-process-is-too-low

 

max file descriptors for elasticsearch process is too low

Cannot resolve these problems: [2017-10-16T13:54:23,381][WARN ][o.e.b.BootstrapChecks ] [node-1] max file descriptors [65000] for elasticsearch process is too low, increase to at least [65536] [

stackoverflow.com

 

 

jpa, spring batch meta table들을 활용할때

 

h2 db를 임의로 초기화하고싶을때가 있다. 

 

근데 truncate할때 fk 등등의 제약조건 걸려서 못할때 (개빡침) 하는 방법

 

 

SET REFERENTIAL_INTEGRITY FALSE --제약조건 무효화

SHOW TABLES

TRUNCATE TABLE {TABLE_NAME}

SET REFERENTIAL_INTEGRITY TRUE --제약조건 재설정

 

 

 

 

stackoverflow.com/questions/27045568/h2-how-to-truncate-all-tables

 

H2 - How to truncate all tables?

I assume there is a way of doing this from code, at least some good workaround. Please consider that I do not want to delete all tables (I've seen this command), just to delete rows from them but to

stackoverflow.com

 

 

 

 

그냥 뭔가 조금 이상했는데 이유는 잘 모르겠다 ..

 

 

querydsl 4.1.4버전을 사용중이였는데 쿼리가 나가는 부분에 UnsupportedOperationException 에러가 발생했다.

 

추적을 좀 해보고싶었는데 구글링해도 도움이 될만한 내용은 찾지 못했다

 

 

일단 querydsl 버전을 4.1.4 -> 4.4.0(20201026 최신버전)  으로 바꾸니까 정상 동작했다.

 

간단하게 디버깅해봤을때

 

com.querydsl.jpa.JPQLSerializer 내부에 아래와 같은 함수가 있는데

    public void visitConstant(Object constant) {
        boolean wrap;
        if (this.inCaseOperation && this.templates.isCaseWithLiterals()) {
            if (constant instanceof Collection) {
                this.append("(");
                wrap = true;

                for(Iterator var5 = ((Collection)constant).iterator(); var5.hasNext(); wrap = false) {
                    Object o = var5.next();
                    if (!wrap) {
                        this.append(", ");
                    }

                    this.visitLiteral(o);
                }

                this.append(")");
            } else {
                this.visitLiteral(constant);
            }
        } else {
            wrap = this.templates.wrapConstant(constant);
            if (wrap) {
                this.append("(");
            }

            this.append("?");
            if (!this.getConstantToLabel().containsKey(constant)) {
                String constLabel = String.valueOf(this.getConstantToLabel().size() + 1);
                this.getConstantToLabel().put(constant, constLabel); // <-- 요기
                this.append(constLabel);
            } else {
                this.append((String)this.getConstantToLabel().get(constant));
            }

            if (wrap) {
                this.append(")");
            }
        }

    }

아래부분에 this.getConstantToLabel().put(constant, constLabel); 로 put을 사용하는데 여기서 사용하는 getConstantToLabel()이 리턴하는 자료구조가 UnmodifiableMap이다.

 

참고로 UnmodifiableMap은 put을 구현하지 않았기 때문에 호출시 UnsupportedOperationException 을리턴하는게당연하다.

 

 

버전을 4.4.0으로 올려서 확인해보면 같은 부분이라도 조금 다른걸 확인할 수 있다.

            this.append("?");
            if (!this.getConstantToAllLabels().containsKey(constant)) {
                Integer constLabel = this.getConstantToNumberedLabel().size() + 1;
                this.getConstantToNumberedLabel().put(constant, constLabel);
                this.append(constLabel.toString());
            } else {
                this.append((String)this.getConstantToAllLabels().get(constant));
            }

getConstantToLabel() -> getConstantToNumberedLabel() 으로 변경된 것을 확인할 수 있는데 실제로 getConstantToNumberedLabel() 가 리턴하는 자료구조는 HashMap이다. 고로 정상동작한다.

 

 

내가 api를 제대로 안본것도 있겠지만 왜 4.1.4 에서는 UnmodifiableMap을 리턴하게 해놨을지 ...

 

 

 

 

 

-결론

버전 올리면 된다.

 

별도로 h2 서버를 띄우지 않고

 

멀티 커넥션을 구성할 수 있는 방법이다

 

spring:
  datasource:
    url: "jdbc:h2:~/e-commerce-dev;AUTO_SERVER=TRUE"

 

 

다음과 같이 AUTO_SERVER=TRUE 옵션을 붙여주면 된다.

 

 

 

 

 

 

 

https://stackoverflow.com/questions/12401991/h2-database-multiple-connections

 

H2 Database multiple connections

I have the following issue: Two instances of an application on two different systems should share a small database. The main problem is that both systems can only exchange data through a network-fo...

stackoverflow.com

 

 

Spring + jpa 환경에서 @WebMvcTest 등등의 슬라이스 테스트 도중 

JPA metamodel must not be empty! 라는 에러메세지를 만나게 될 경우 해결 방법이다.

 

아마 다음과 같이 bootstrapping 클래스인 ***Application의 모습이 다음과 같을 것이다

 

 

 

package me.sup2is.order;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;

@SpringBootApplication
@EnableJpaAuditing
public class OrderServiceApplication {

    public static void main(String[] args) {
        SpringApplication.run(OrderServiceApplication.class, args);
    }

}

 

슬라이스 테스트던 어떤 테스트던 가장 기본이 되는 bootstrapping 클래스는 항상 로딩이된다.

이때 @EnableJpaAuditing 이 붙은 bootstrapping 클래스가 스프링 부트에 의해 로딩되는데 @WebMvcTest같은 테스트 전용 애너테이션은 JPA 관련 빈들을 로딩하지 않기 때문에 일어나느 현상이다. 

 

따라서 다음과 같이 별도의 configuration 클래스를 생성해서 @EnableJpaAuditing 을 붙여주면 해결된다.

 

@Configuration
@EnableJpaAuditing
public class JpaAuditingConfiguration {}

 

 

 

 

 

https://stackoverflow.com/questions/60606861/spring-boot-jpa-metamodel-must-not-be-empty-when-trying-to-run-junit-integrat

 

Spring Boot JPA metamodel must not be empty! when trying to run JUnit / Integration Tests

Am using Spring Boot, JUnit 4 & Mockito in a maven based project to tests my Spring Boot Microservice REST API. So, on startup, the DataInserter class loads data from owner.json and cars.json.

stackoverflow.com

 

+ Recent posts