Spring은 사용하려는 프로파일을 정의하여 상황에 따라 컴포넌트에 대한 등록 및 제외를 결정할 수 있다.

@Profile({"dev", "!kr"})

이라고 프로파일을 정의하면 조건식은 dev or !kr 이 되어 dev 혹은 kr 에 대해서 선언되어 있지 않으면 반드시 실행되는 상황이 발생한다.

이런 상황을 피할 수 있는 방법으로 Spring 4.0에서 추가된 @@Conditional 을 사용하는 방법이 있다. 이와 관련한 질문은 How to conditionally declare Bean when multiple profiles are not active? 를 살펴보면 고민하고 있는 유사한 내용과 답변을 볼 수 있다.

간단한 해결책은 Condition을 구현하는 것이다. 다음과 같이 간단하게 dev and !kr을 만족하는 조건식을 작성해보자.

import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
public class PrdAndIgnoreKrProfileCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return context.getEnvironment().acceptsProfiles("prd") && !context.getEnvironment().acceptsProfiles("kr");
}
}

위의 클래스를 사용하여

@Profile({"dev", "!kr"})
//을 대신하여
@Conditional(PrdAndIgnoreKrProfileCondition.class)
// 으로 정의하면 dev and !kr 조건식이 적용가능해진다.


  1. azz 2019.04.17 08:53

    only dev 와 dev and !kr과 어떤게 다른건가요? 같아보이는데.

    • 실행환경 프로파일로 사용한 dev
      로케일 프로파일로 사용한 kr

      dev 하나만 사용하는 환경이라면 kr은 큰 의미가 없죠.

      로케일 프로파일로 vn, ph, jp 등을 사용하는 상황에서 한국 로케일 관련한 활성화를 막을 필요가 있을 때 필요합니다.

      or 조건에서는 어느 한쪽만 맞아도 true가 되어 활성화되지만 and 조건에서는 두 가지 조건이 모두 맞아야 활성화됩니다.


Thymeleaf 에서 스프링 환경변수 사용하기

Thymeleaf 에서 스프링 프로퍼티 값 사용하는 방법

  • @ 뒤에 빈(Bean) 이름을 사용하면 그 빈에 접근할 수 있다.

타임리프에서 스프링의 property 파일(application.property 혹은 application.yml 등)에 기술되어 있는 변수를 이용하려는 경우

${@environment.getProperty('property.key')}

프로파일 환경에 따라 표시를 하려면

<div th : if = $ { @environment .acceptsProfiles ( 'production' )}>
This is the production profile
</ div>
or
<div th : if = "$ {# arrays.contains (@ environment.getActiveProfiles () 'production')} " >
     This is the production profile
</ div>

시스템 환경변수를 이용하는 경우

$ { @systemProperties [ 'property.key' ]}


바보, 삽질을 하다.

public class WBAccessDeniedHandler implements AccessDeniedHandler {
 
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOExceptionServletException {
        String redirectUrl = "/";
        response.sendRedirect(redirectUrl);
    }
}

redirectUrl 는 반드시 / 으로 시작해야 한다. 안그러면…​ 접근한 requestUrl 에 끊없이 redirectUrl 붙다가 오류가 난다.


발생문제

org.hibernate.loader.MultipleBagFetchException: cannot simultaneously fetch multiple bags: [entity.list_collection_a, entity.list_collection_b]
@ElementCollection(targetClass = EnumType.class, fetch = FetchType.EAGER)
@Enumerated(EnumType.STRING)

해당필드는 enum 타입의 목록을 가지는 필드였고, 프로젝트의 의존성 라이브러리 버전들을 업그레이드 하면서org.hibernate.loader.MultipleBagFetchException 이 발생했다.

  • 업그레이드

    • org.hibernate:hibernate-entitymanager:5.1.0.Final →org.hibernate:hibernate-entitymanager:5.2.4.Final

해결방법

이 문제를 해결하는 방법은 enum 타입 컬렉션 필드에 정의를 다음과 같이 변경했다.

@ElementCollection(targetClass = EnumType.class)
@Enumerated(EnumType.STRING)
@LazyCollection(LazyCollectionOption.FALSE)

@ElementCollection 는 기본적으로 LAZY 값을 가진다. 그러나 한단에 선언된@LazyCollection(LazyCollectionOption.FALSE) 을 통해서 EAGER 로 처리된다.@LazyCollection 는 컬렉션 타입에 대한 LAZY 여부를 결정하는 기능을 한다.


+ Recent posts