fix: MessageConverterImpl convertToTypedObject의 null List/Record NullPointerException 방지 - #305
Open
z3rotig4r wants to merge 1 commit into
Open
Conversation
…PointerException 방지
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
변경 이유
MessageConverterImpl.convertToTypedObject()의 List 분기와 Record 분기가source를 널 검사 없이 역참조합니다. List 분기는(Object[]) source를 그대로 순회하고 Record 분기는Field.get(source)를 호출하므로, source가 null이면 NullPointerException이 발생합니다.null은 실제 호출 경로에서 들어옵니다.
EgovWebServiceClientImpl(355~360행)은 OUT·INOUT 파라미터를new Holder<Object>()로 만들어 넘깁니다. 응답 메시지에 해당 요소가 없으면Holder.value가 null인 채 변환기에 도달합니다.ServiceBridgeImpl(110~117행)은 인바운드 요청에서 IN 파라미터가 빠지면params.get(name)이 null을 돌려줍니다.두 호출처 모두
ClassNotFoundException·IllegalAccessException·IllegalArgumentException·InstantiationException·NoSuchFieldException만 잡습니다. NullPointerException은 이 목록에 없어 호출 스택 위로 그대로 전파됩니다.EgovWebServiceClientImpl은 응답 파싱을 가능한 만큼 수행하고 실패분을FAIL_IN_PARSING_RESPONSE_MESSAGE결과코드로 돌려주도록 설계되어 있는데, NPE가 그 부분 실패 처리 경로를 건너뜁니다.새 정책을 도입하는 변경이 아니라 이미 정해진 계약에 구현을 맞추는 변경입니다. 프레임워크 타입 체계는 null을 유효한 값으로 규정합니다.
ListType.convertToTypedObject()(114116행),137행),RecordType.convertToTypedObject()(135PrimitiveType의 모든 구현이 source가 null이면 null을 반환합니다.isAssignableValue(null)도 세 타입 모두 true입니다. 같은 메서드의 Primitive 분기(114~116행) 역시 이미 null을 그대로 반환합니다. List·Record 분기만 예외로 남아 있었습니다.역방향 메서드인
convertToValueObject()에는 같은 가드가 이미 반영되어 있습니다(#269). 두 메서드는 서로 역함수이고 같은 호출처에서 짝으로 쓰입니다. 클라이언트는 요청 생성(289행)과 응답 파싱(360행)에서, 서버 브리지는 요청 파싱(117행)과 응답 생성(195행)에서 각각 호출합니다. 이번 수정으로 양방향의 null 처리가 대칭이 됩니다.변경 내용
convertToTypedObject()의 List 분기와 Record 분기에source가 null이면 null을 반환하는 가드를 각각 추가했습니다.Type이 들어왔을 때InstantiationException을 던지는 현재 계약까지 null 반환으로 바뀝니다. 분기별 배치는 그 계약을 그대로 보존합니다.convertToValueObject()에 이미 있는 가드와 형태도 같습니다.테스트 방법
org.egovframe.rte.itl.webservice모듈 테스트 19건이 모두 통과합니다(신규 3건 포함, 실패·오류 0건).회귀 여부는 본문 수정만 되돌리고 테스트만 적용해 확인했습니다. 이 상태에서 신규 3건이 모두 NullPointerException으로 실패합니다.
testConvertToTypedObjectWithNullListSource—Cannot read the array length because "components" is nulltestConvertToTypedObjectWithNullRecordSource—Cannot invoke "Object.getClass()"testConvertToTypedObjectWithNullListField— 재귀 호출로 List 분기에서 같은 지점이 실패영향 범위
MessageConverterImpl.java(본문 10줄)와 같은 모듈의 테스트MessageConverterImplTest.java(33줄) 두 개입니다.