Skip to content

fix: EgovWebServiceMessageHeader.setResultCode 가 null 을 막지 못해 응답 헤더 복사가 죽는 문제 수정 - #361

Open
wantaekchoi wants to merge 1 commit into
eGovFramework:mainfrom
wantaekchoi:fix/wsmsgheader-null-resultcode
Open

fix: EgovWebServiceMessageHeader.setResultCode 가 null 을 막지 못해 응답 헤더 복사가 죽는 문제 수정#361
wantaekchoi wants to merge 1 commit into
eGovFramework:mainfrom
wantaekchoi:fix/wsmsgheader-null-resultcode

Conversation

@wantaekchoi

Copy link
Copy Markdown
Contributor

수정 사유 Reason for modification

  • 버그수정 Bug fixes
  • 기능개선 Enhancements
  • 기능추가 Adding features
  • 기타 Others

수정된 소스 내용 Modified source

EgovWebServiceMessageHeader 는 읽기 쪽과 쓰기 쪽이 어긋나 있습니다. getResultCode() 는 결과 코드가 빈 헤더에서 null 을 돌려주는데, setResultCode(ResultCode) 는 인자를 검사 없이 역참조합니다.

// EgovWebServiceMessageHeader.java:358-360
public ResultCode getResultCode() {
    return ResultCode.getCode(resultCode);
}

// EgovWebServiceMessageHeader.java:367-369
public void setResultCode(ResultCode resultCode) {
    this.resultCode = resultCode.getValue();
}

ResultCode.getCodecodes.get(value) 뿐이라, 값이 없으면 예외 없이 null 이 나옵니다(EgovIntegrationMessageHeader.java:417-419).

둘을 이어 붙이는 곳이 같은 클래스의 복사 생성자(120줄)입니다. 132줄 setResultCode(header.getResultCode()); 가 자기 getter 가 만든 null 을 자기 setter 에 그대로 넣습니다.

서버 진입점 ServiceBridgeImpl.doService() 는 정상 분기(155-161줄)에서 요청 헤더를 그 생성자에 그대로 넘깁니다(ServiceBridgeImpl.java:161, new EgovWebServiceMessageHeader(requestHeader)).

트리거가 넓지는 않습니다. EgovWebService 가 기본 헤더를 ResultCode.OK 로 채워(EgovWebService.java:114) createRequestMessage() 를 거친 eGov 클라이언트 요청은 이 null 을 만들지 않습니다. 남는 것은 외부 SOAP 클라이언트가 보낸 헤더와 직접 조립한 헤더입니다. 결과 코드는 응답이 산출하는 값이라 요청자가 채울 이유가 없고, 필드가 protected String resultCode(101줄)라 JAXB 는 없는 엘리먼트를 null 로 남깁니다.

빈도가 아니라 한 클래스 안에서 읽기 쪽이 허용하는 값을 쓰기 쪽이 못 받는다는 점이 문제라고 봤습니다. 형제 구현은 같은 자리에서 null 을 그대로 받습니다.

// SimpleMessageHeader.java:247-249
public void setResultCode(ResultCode resultCode) {
    this.resultCode = resultCode;
}

SimpleMessageHeader 는 필드가 protected ResultCode resultCode(94줄)라 대입만 하면 되고, 이쪽은 JAXB 직렬화 때문에 String 필드를 써 enum → String 변환이 필요합니다. 인터페이스 EgovIntegrationMessageHeader 의 선언(186줄, 193줄)에도 non-null 제약은 없습니다.

AS-IS / TO-BE

 public void setResultCode(ResultCode resultCode) {
-    this.resultCode = resultCode.getValue();
+    this.resultCode = resultCode != null ? resultCode.getValue() : null;
 }

null 을 저장하면 getResultCode()ResultCode.getCode(null) 로 다시 null 을 돌려주어 읽기 쪽과 왕복이 맞습니다. 기본값 ResultCode.OK 를 채우면 결과 코드를 모르는 헤더가 정상 종료로 보이고 형제 SimpleMessageHeader 와도 갈라집니다.

호출부마다 막지 않고 setter 한 곳을 고쳤습니다. 복사 생성자와 전체 인자 생성자가 모두 이 메서드를 지납니다.

영향 범위

인자가 null 일 때의 동작만 바뀝니다.

이 복사 생성자를 쓰는 자리는 src/main 안에 16곳입니다(EgovWebService 4곳, EgovWebServiceClientImpl 6곳, ServiceBridgeImpl 6곳). 그중 요청 헤더로 응답 헤더를 만드는 12곳(EgovWebServiceClientImpl 6곳, ServiceBridgeImpl 6곳)이 같이 닫힙니다. 나머지 4곳은 EgovWebService 가 자기 기본 헤더를 넘기는 자리입니다.

형제 TypedMessageHeader 도 267줄에서 같은 무가드 역참조를 하고 262-263줄 getter 는 null 을 허용합니다. 다만 복사 생성자가 없어 이 경로로는 도달하지 않고, 모듈도 itl.integration 이라 범위에서 뺐습니다.

JUnit 테스트 JUnit tests

  • JUnit 테스트 JUnit tests
  • 수동 테스트 Manual testing

EgovWebServiceMessageHeaderNullResultCodeTest 를 더했습니다. 헤더를 손으로 조립하지 않고, resultCode 엘리먼트가 없는 헤더 XML 을 JAXB 로 언마샬해 ServiceBridgeImpl 이 받는 것과 같은 객체를 복사 생성자에 넣습니다.

수정을 뺀 상태입니다(패키지 접두어 생략).

$ mvn -o test -pl Integration/org.egovframe.rte.itl.webservice
unmarshalled getResultCode() = null
SimpleMessageHeader copy OK, resultCode = null
[ERROR] Tests run: 3, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.234 s <<< FAILURE! -- in EgovWebServiceMessageHeaderNullResultCodeTest
[ERROR] Tests run: 25, Failures: 0, Errors: 1, Skipped: 0
[INFO] BUILD FAILURE

target/surefire-reports 의 스택입니다.

java.lang.NullPointerException: Cannot invoke "org.egovframe.rte.itl.integration.EgovIntegrationMessageHeader$ResultCode.getValue()" because "resultCode" is null
	at EgovWebServiceMessageHeader.setResultCode(EgovWebServiceMessageHeader.java:368)
	at EgovWebServiceMessageHeader.<init>(EgovWebServiceMessageHeader.java:132)
	at EgovWebServiceMessageHeaderNullResultCodeTest.copyConstructorAcceptsHeaderWithoutResultCode(EgovWebServiceMessageHeaderNullResultCodeTest.java:41)

수정 후 같은 명령입니다.

[INFO] Tests run: 25, Failures: 0, Errors: 0, Skipped: 0
[INFO] BUILD SUCCESS

기존 22건은 수정 전후 모두 통과하고, 새 테스트 3건이 더해져 25건입니다. 그중 EgovWebServiceTest 7건에 EchoEgovWebServiceClient 가 같은 복사 생성자를 쓰는 경로가 있습니다(EgovWebServiceTest.java:250-251).

컨테이너를 띄운 SOAP 왕복 확인은 하지 않았습니다.

테스트 브라우저 Test Browser

  • Chrome
  • Firefox
  • Edge
  • Safari
  • Opera
  • Internet Explorer
  • 기타 Others

테스트 스크린샷 또는 캡처 영상 Test screenshots or captured video

화면이 없는 실행환경 모듈이라 첨부하지 않았습니다.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant