보고서에 첨부를 선택하고 저장하면 커밋 전체가 롤백됐다. base64 문자열이 커서 생긴 문제로 보고 첨부 저장 방식을 FileDocument로 바꿨지만 그대로였다. 실제 원인은 Enum 속성에 없는 값을 보낸 것이었다.
문제
첨부 없이 저장하면 성공, 첨부를 선택하면 실패. 작은 파일도, 큰 파일도 똑같이 실패
원인
첨부 여부를 담는 속성이 보고서마다 타입이 달랐음. 0보는 String, 1보와 2보는 Enumeration. 위젯이 보낸 값이 Enum 값 목록에 없었음
해결
같은 용도의 속성 타입을 String으로 통일. 첨부 저장은 FileDocument로 전환한 상태 유지
증상을 다시 보면 크기와 무관했다
| 조건 | 보내는 값 | 결과 |
|---|---|---|
| 첨부 없이 저장 | SystemWrite | 성공 |
| 작은 파일 첨부 | Attachment | 롤백 |
| 큰 파일 첨부 | Attachment | 롤백 |
| 0보에 첨부 | Attachment (String 속성) | 성공 |
첫 오류 로그에도 단서가 있었다. 속성 이름과 함께 Attachment 값이 찍혀 있었는데, 옆에 붙은 긴 base64 문자열에 시선이 가서 용량 문제로 판단했다. Caused by를 끝까지 따라가자 InvalidEnumerationValueException이 나왔다.
로그에서 찾아야 할 줄
ERROR - ... (커밋 실패, 긴 base64 문자열이 함께 출력됨)
...
Caused by: ...InvalidEnumerationValueException ... Report1_Method ... 'Attachment' ...Enum은 Caption이 아니라 Name으로 비교한다JS에서 Enum 속성에 값을 넣을 때는 화면에 보이는 Caption이 아니라 Name을 보내야 한다. 값 목록에 없는 Name이 들어가면 해당 객체를 포함한 커밋 전체가 롤백된다.
그래도 FileDocument로 바꾼 이유
롤백 원인과는 별개로, base64 문자열 저장은 다른 문제를 만들고 있었다.
| 구분 | base64 문자열 속성 | FileDocument |
|---|---|---|
| 저장 위치 | DB 행 안 | 파일 저장소, DB엔 정보만 |
| 객체 조회 시 | 파일 내용까지 함께 로드 | 파일 내용은 따로 |
| 크기 제한 | 요청 크기, 메모리에 좌우 | 업로드 한도로 관리 |
| 내려받기 | JS에서 디코딩 | 파일 URL로 바로 |
관련 글: 5편 Mendix Java heap OOM 추적기
JS 위젯에서 FileDocument 다루기
JS: 파일 업로드
var MAX_SIZE = 10 * 1024 * 1024; // 10MB
function uploadFile(file, ownerGuid, onDone) {
if (file.size > MAX_SIZE) { showMessage('10MB 이하 파일만 첨부할 수 있습니다.'); return; }
mx.data.create({
entity: 'Report.Attachment', // System.FileDocument 상속
callback: function (doc) {
doc.set('Report.Attachment_Report', ownerGuid); // 보고서와 연결
mx.data.saveDocument(doc.getGuid(), file.name, {}, file,
function () { onDone(null, doc.getGuid()); },
function (err) { onDone(err); });
},
error: function (err) { onDone(err); }
});
}JS: 내려받기 링크
function downloadUrl(guid) {
return '/file?guid=' + encodeURIComponent(guid);
}기존 base64 컬럼은 바로 지우지 않았다과거에 저장된 첨부를 조회할 수 있어야 해서 기존 속성은 남겨 두고, 새 첨부만 FileDocument로 저장했다.
같이 고친 두 가지
행을 지우고 다시 만드는 저장 방식
결과보고 표는 저장할 때 기존 행을 모두 지우고 새로 만들었다. 행에 연결된 첨부가 같이 끊겼다. 행은 그대로 두고 값만 갱신하도록 바꿨다.
저장은 되는데 화면에 안 보이는 문제
목록 JSON에는 용량이 큰 필드를 넣지 않는다. 그래서 팝업을 열 때 목록 데이터를 그대로 쓰면 첨부와 본문이 비어 보인다. 팝업을 열 때 해당 건만 다시 조회하도록 했다. 이 문제는 첨부, 보고서 본문 등에서 여러 번 반복됐다.
JS: 팝업 열 때 상세 재조회
function openPopup(guid) {
mx.data.get({
guid: guid,
callback: function (obj) { fillForm(obj); loadAttachments(guid); },
error: function () { showMessage('상세 정보를 불러오지 못했습니다.'); }
});
}점검 목록
- 오류 로그의 Caused by를 마지막 줄까지 읽었는가
- 같은 용도의 속성이 엔티티마다 같은 타입인가
- JS에서 Enum 값으로 Name을 보내는가
- 첨부는 FileDocument로 저장하고 크기 제한을 화면과 서버 양쪽에 걸었는가
- 목록 JSON에서 뺀 필드를 상세 화면에서 다시 조회하는가
시리즈 목차 16편
- PI 담당자가 로우코드로 사내 시스템을 직접 만들고 운영한 기록
- Mendix Datagrid2 대신 HTMLSnippet과 JS로 목록 화면 만들기
- Mendix SPA에서 HTMLSnippet JS가 꼬이는 이유: 이벤트 중복과 DOM 공존
- Mendix mx.data.commit이 조용히 실패할 때
- Mendix Java heap OOM 추적기: base64 이미지 컬럼
- Mendix 커밋 롤백, 용량 문제가 아니었다: FileDocument 전환기 (현재 글)
- Mendix 첫 접속 지연 줄이기: 워밍업과 캐시
- Mendix SAML SSO 자동 로그인과 딥링크 유지
- Mendix Studio Pro에서 안 바뀌는 스타일 main.scss로 바꾸기
- Mendix MPK 파일 열어서 마이크로플로우 구조 보기
- SSO 로그 테이블로 MAU와 재방문율 구하는 SQL
- Mendix DateTime이 BI 도구에서 하루 빠르게 보이는 이유
- 대시보드 숫자가 틀렸을 때 확인하는 순서
- 보기 좋은 대시보드에서 할 일을 알려주는 대시보드로
- 여러 점검 시스템을 하나로 합치는 데이터 모델
- 데이터 비전공자에게 분석 결과 보고하기