web/Spring

lombok에서 @builder annotation 사용 후 static 접근 시 cannot find symbol 에러 문제

반응형

문제상황


개발하면서 특정 정보를 필터링할 Predicate를 동적으로 생성하고 싶은 마음에 다음과 같이 개발을 진행했었다.

 

WedulFilterPredicate

- 필터로 사용할 조건을 보관하고 Predicate를 반환하는 클래스

package com.wedul.springtest;

import lombok.Builder;
import lombok.Getter;

import java.util.function.Predicate;

@Getter
public class WedulFilterPredicate {

    private Boolean hasName;
    private Boolean hasPicture;
    private String teamNo;

    @Builder
    public WedulFilterPredicate(Boolean hasName, Boolean hasPicture, String teamNo) {
        this.hasName = hasName;
        this.hasPicture = hasPicture;
        this.teamNo = teamNo;
    }

    public Predicate createPredicate() {
        if (hasPicture && teamNo != null) {
            return data -> data.equals(teamNo);
        }
        return data -> false;
    }
}

 

WedulFilter

- 조건별 필터(WedulFilterPredicate)를 생성할 수 있도록 static builder를 반환하는 메소드를 정의한 인터페이스

package com.wedul.springtest.filter;

import com.wedul.springtest.WedulFilterPredicate;

public interface WedulFilter {
    WedulFilterPredicate.WedulFilterPredicateBuilder predicateBuilder();
}

 

WedulPosPredicate

- 조건 별 Enum value로 value에 따라 WedulFilterPredicate 클래스를 생성할 수 있도록 하는 static WedulFilterPredicateBuilder를 반환할 수 있도록 하는 enum 클래스

package com.wedul.springtest;

import com.wedul.springtest.filter.WedulFilter;

public enum WedulPosPredicate implements WedulFilter {
    HAS_NAME {
        @Override
        public WedulFilterPredicate.WedulFilterPredicateBuilder predicateBuilder() {
            return WedulFilterPredicate.builder()
                    .hasName(true);
        }
    },
    HAS_PHOTOS {
        @Override
        public WedulFilterPredicate.WedulFilterPredicateBuilder predicateBuilder() {
            return WedulFilterPredicate.builder()
                    .hasPicture(true);
        }
    }
}

 

WedulPosDomainService

- HAS_PHOTO조건에 맞는 Predicate를 WedulPosPredicate에서 받고 입력받은 teamNo를 사용하여 WedulFilterPredicate를 만들어서 predicate를 반환하는 서비스

package com.wedul.springtest;

import org.springframework.stereotype.Service;

import java.util.function.Predicate;

@Service
public class WedulPosDomainService {

    public Predicate getHasPhotoWedulPosPredicate(String teamNo) {
        WedulFilterPredicate wedulFilterPredicate = WedulPosPredicate.HAS_PHOTOS
                .predicateBuilder()
                .teamNo(teamNo)
                .build();

        return wedulFilterPredicate.createPredicate();
    }

}

 

동일하지는 않지만 이런식으로 요청받은 filter값을 사용해서 Predicate를 생성하는 로직이었다. 크게 문제가 없이 동작할 것으로 보이지만 해당 코드를 돌려보면 error: cannot find symbol 에러가 발생한다.

 

/Users/jeongcheol/Documents/project/springtest/src/main/java/com/wedul/springtest/filter/WedulFilter.java:6: error: cannot find symbol
    WedulFilterPredicate.WedulFilterPredicateBuilder predicateBuilder();
                        ^
  symbol:   class WedulFilterPredicateBuilder
  location: class WedulFilterPredicate

 

원인파악


위 코드에서 다른 부분이 중요한 것이 아니라 WedulFilter에서 WedulFilterPredicate.WedulFilterPredicateBuilder를 반환하고 있는 이부분에서 WedulFilterPredicateBuilder를 못찾는다는 것이다. 

 

왜 못찾는 것인가? 그냥 봤을때는 lombok의 builder 애노테이션을 사용하게 되면 static 클래스를 생성해서 접근해서 사용할 수 있도록 하기 때문에 큰 문제가 없을거라고 생각하게된다. 실제 Delombok을 해서 생성되는 코드를 봐도 WedulFilterPredicateBuilder클래스가 만들어져서 큰 문제없이 접근이 가능할것이라고 보인다. 

public static class WedulFilterPredicateBuilder {
        private Boolean hasName;
        private Boolean hasPicture;
        private String teamNo;

        WedulFilterPredicateBuilder() {
        }

        public WedulFilterPredicateBuilder hasName(Boolean hasName) {
            this.hasName = hasName;
            return this;
        }

        public WedulFilterPredicateBuilder hasPicture(Boolean hasPicture) {
            this.hasPicture = hasPicture;
            return this;
        }

        public WedulFilterPredicateBuilder teamNo(String teamNo) {
            this.teamNo = teamNo;
            return this;
        }

        public WedulFilterPredicate build() {
            return new WedulFilterPredicate(hasName, hasPicture, teamNo);
        }

        public String toString() {
            return "WedulFilterPredicate.WedulFilterPredicateBuilder(hasName=" + this.hasName + ", hasPicture=" + this.hasPicture + ", teamNo=" + this.teamNo + ")";
        }
    }

 

 

하지만 동작하지 않았던 원인은 lombok의 동작방식을 보면 알 수 있는데 lombok을 사용할 때 AnnotationProcessor를 사용해서 코드를 생성해서 사용한다는것을 알고 있다. 

 

하지만 static import는 annotation processor가 동작하기전에 진행되기 때문에 javac 컴파일 시점에 WedulFilterPredicateBuilder를 찾지 못하기 때문에 발생하는 문제였다. 

 

 

해결방법


WedulFilterPredicateBuilder static class 미리 생성

위 에러의 문제가 static import 작업 시 lombok의 생성내용을 알지 못하기 때문에 발생하는 것으로 lombok이 생성하는 static class 껍데기를 미리 생성하는 것이다. 그럼 의문이 들수 있는 부분이 나중에 Lombok이 코드를 생성할 때 문제가 되는거 아니야? 라고 생각할 수 있다. 하지만 실제 롬복에 의해서 코드가 생성되는 시점에 해당 클래스에 내용물을 채워지기 때문에 동작에 문제가 없다. 

package com.wedul.springtest;

import lombok.Builder;
import lombok.Getter;

import java.util.function.Predicate;

@Getter
public class WedulFilterPredicate {

    private Boolean hasName;
    private Boolean hasPicture;
    private String teamNo;

    @Builder
    public WedulFilterPredicate(Boolean hasName, Boolean hasPicture, String teamNo) {
        this.hasName = hasName;
        this.hasPicture = hasPicture;
        this.teamNo = teamNo;
    }

    public static class WedulFilterPredicateBuilder {}

    public Predicate createPredicate() {
        if (hasPicture && teamNo != null) {
            return data -> data.equals(teamNo);
        }
        return data -> false;
    }

}

 

 

 

http://www.miredot.com/docs/faq/q/cannot-find-symbol-during-javadoc-phase/

 

Miredot | Lombok's @Builder annotation causes a cannot find symbol error during the javadoc phase.

documentation home FAQ  Lombok's @Builder annotation causes a cannot find symbol error during the javadoc phase. Problem You get the following error during the javadoc phase when using Lombok's @Builder annotation. javadoc: Constructing Javadoc informati

www.miredot.com

 

 

https://github.com/projectlombok/lombok/issues/979

 

Static import of builder class breaks bytecode generation in Maven · Issue #979 · projectlombok/lombok

I have a class Foo annotated with @builder. @Builder public class Foo { ... } I use the generated class Foo.FooBuilder in Bar, but I statically import Foo.Builder so that I can refer directly to Fo...

github.com

https://stackoverflow.com/questions/34358689/maven-build-cannot-find-symbol-when-accessing-project-lombok-annotated-methods

 

Maven build cannot find symbol when accessing project lombok annotated methods,

I'm using project lombok for the first time and I have problems compiling the project via maven when I run the build I receive errors where methods annotated with project lombok annotations are cal...

stackoverflow.com

https://stackoverflow.com/questions/47674264/static-import-not-working-in-lombok-builder-in-intellij

 

static import not working in lombok builder in intelliJ

I am using Lombok in IntelliJ. Though everything else is working fine when I try to do the static import of the Lombok builder, IntelliJ build project doesn't find the builder class. If you don't use

stackoverflow.com

 

반응형