⚠️[SpringBoot] - SpelEvaluationException: EL1007E

dev_itzel_02✨·2025년 4월 20일

⚠️Trouble Shooting

목록 보기
10/10
post-thumbnail
**2025-04-16T21:11:43.487+09:00 ERROR 12360 --- 
[Jinus] [nio-5100-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: 
org.springframework.expression.spel.SpelEvaluationException: EL1007E: Property or field 'dietDate' cannot be found on null] with root cause**

카카오톡 테스트 챗봇으로 ‘식단 조회’ 시 발생한 오류이다.


[Chat-GPT 오류 분석]

SpEL

Spring Expression Language

${….} or #{….} 식을 해석하려고 했는데, 해당 표현식에서 참조한 dietDate 속성이 null 객체에 대해 호출되었기 때문에 발생한 예외

  • dietDate 속성을 찾음
  • 해당 속성이 붙은 객체가 null 상태임
    • RequestDto로 파라미터들을 객체로 묶어놓음
    • RequestDto 객체가 null이라는 말
  • 즉, null.dietDate를 참조한 상황

⇒ 로그를 확인해 관련 객체가 null이 아닌지 체크

[식단 조회 과정 디버깅 실행]

모든 파라미터들은 값이 잘 들어간 상태

→ 즉, RequestDto 객체는 null 이 아님

오류가 발생하는 지점

DietQueryServiceV2getDiets 메소드 내 코드에서 발생

List<DietDto> dietDtos = cacheServiceV2.getDietList(parameters, cafeteriaId);

디버깅을 따라가보면 이 코드 이후에 InvocableHandlerMethod 클래스 내의 doInvoke 메소드의 try-catch 문에서 InvocationTargetException 예외처리에서 걸림

catch (InvocationTargetException var9) {
    InvocationTargetException ex = var9;
    Throwable targetException = ex.getCause();
    if (targetException instanceof RuntimeException runtimeException) {
		    throw runtimeException;

if문까지 실행된 후 runtimeException이 던져짐

그 후, DispatcherServlet 클래스의 doDispatch 메소드의 try-catch 문에서 Exception 예외에서 걸림

catch (Exception var20) {
		Exception ex = var20;
    dispatchException = ex;

그 후, catch 문을 벗어난 후 아래 문장 실행

this.processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException);
catch (Exception var22) {
    Exception ex = var22;
    triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
finally {
		if (asyncManager.isConcurrentHandlingStarted()) {
		    if (mappedHandler != null) {
		        mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
        }
    } else if (multipartRequestParsed) {
		      this.cleanupMultipart(processedRequest);
    }
  • 첫 번째 if문을 실행 → false
  • else-if 문 실행 → false
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception

이 메소드에서 source code does not match bytecode라는 오류가 종종 뜸

그 후, doService 메소드로 이동

등등 그 후에도 여러 예외들로 계속 전파되어 콘솔에 오류 발생

결론적으로는 SpEL 오류라는 것.

이 코드를 자세히 보면 java.lang.reflect.InvocationTargetException 이 발생함

이 예외로 빠진다는 건, cacheServiceV2.getDietList 호출 내부에서 리플렉션으로 메서드를 호출하다가 예외가 터졌다는 의미

⚠️[InvocationTargetException]

리플렉션을 통해 메서드를 호출할 때, 그 메서드 내부에서 예외가 발생하면 그 예외를 감싸서 던지는 예외

Method method = someClass.getMethod("someMethod");
try {
    method.invoke(someObject);  // ← 내부에서 예외 발생하면
} catch (InvocationTargetException e) {
    Throwable realCause = e.getCause();  // 실제 예외 원인
}

[확인해야 할 것]

  • getDietList내부에서 리플렉션을 사용하고 있는지 ? ⇒ NO
  • 리플렉션 호출 대상 메서드에서 SpEL을 사용하는 로직이 있는지 ? ⇒ NO
  • 캐시 관련 로직에서 SpEL을 key로 사용하고 있는지 ? ⇒ YES,,

@Cacheable(key = "#parameters.dietDate") 캐시 키값 설정을 위해 해당 코드를 사용중이었음

#parametersnull이어서 .dietDate 접근할 수 없다는 뜻.

[예외 흐름 요약]

  • cacheServiceV2.getDietList(parameters, cafeteriaId) 호출
  • 내부에서 @Cacheable 애너테이션 처리 중 → SpEL 평가 수행
  • SpEL 평가 중 parameters가 null → SpelEvaluationException 발생
  • 이 예외는 리플렉션을 통해 메서드가 호출됐기 때문에 InvocationTargetException으로 감싸짐

[결론]

SpEL 문법 오류

[해결]

SpEL에서 null-safe 연산자 ?. 사용하기

@Cacheable(
    value = "dietList",
    key = "#parameters?.dietDate + '::' + #parameters?.period + '::' + #cafeteriaId",
    ...
)

이것만 수정하고 나니 실제로 오류는 해결됨

(하지만, SpEL 오류의 근본적인 이유와 dietDate 속성값은 null이 아닌데 null로 인식되는 이유를 모르겠음)

[추가로 알아볼 것]

  • 리플렉션
  • SpEL
profile
🐜👣steadiness🐜👣

0개의 댓글