Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| bf4f953d56 | |||
| 814571eeba | |||
| 13850ba329 | |||
| 04b4d415a9 | |||
| 38902cf6b3 | |||
| 7ebbd7d9e4 | |||
| f59de66d2c | |||
| c179e50047 | |||
| 39f0baf5ef | |||
| 08354837b1 | |||
| a31b991e59 | |||
| 615e56687a | |||
| ba1161be7b | |||
| 7430b03323 | |||
| 5b05489924 | |||
| 3c386b780b | |||
| f928a0b1e4 | |||
| dc9e737aa9 | |||
| db57e95233 | |||
| 643e7fcdf2 | |||
| 36994a57b6 | |||
| 4a087e576b | |||
| 9f22d4fa4d | |||
| 66c01029cd |
@@ -31,6 +31,8 @@ function init(){
|
|||||||
new makeOptions("CODE","NAME").setObj($("select[name=searchJobInst]")).setNoValueInclude(true).setNoValue("",
|
new makeOptions("CODE","NAME").setObj($("select[name=searchJobInst]")).setNoValueInclude(true).setNoValue("",
|
||||||
"<%= localeMessage.getString("combo.all")%>").setData(json.instanceList).rendering();
|
"<%= localeMessage.getString("combo.all")%>").setData(json.instanceList).rendering();
|
||||||
|
|
||||||
|
$("select[name=searchJobUseYn]").val("Y");
|
||||||
|
|
||||||
putSelectFromParam();
|
putSelectFromParam();
|
||||||
|
|
||||||
initGrid();
|
initGrid();
|
||||||
|
|||||||
@@ -45,6 +45,9 @@
|
|||||||
background-color: #EDD5DD
|
background-color: #EDD5DD
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.btn_move { width:32px; min-width: 32px; height: 32px; background-color: #fff; border:1px solid #999; border-radius:4px; margin-bottom: 4px; }
|
||||||
|
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
<jsp:include page="/jsp/common/include/script.jsp"/>
|
<jsp:include page="/jsp/common/include/script.jsp"/>
|
||||||
<script language="javascript" src="<c:url value="/js/jsplumb.js"/>"></script>
|
<script language="javascript" src="<c:url value="/js/jsplumb.js"/>"></script>
|
||||||
@@ -888,7 +891,7 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$("input[name=auto]").click(function(){
|
$("#auto").click(function(){
|
||||||
//debugger;
|
//debugger;
|
||||||
jsPlumbInstance.deleteEveryConnection();
|
jsPlumbInstance.deleteEveryConnection();
|
||||||
|
|
||||||
@@ -915,7 +918,7 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$("input[name=addAll]").click(function() {
|
$("#addAll").click(function() {
|
||||||
console.debug('addAll');
|
console.debug('addAll');
|
||||||
var srcRowId = sourceGrid.getGridParam( "selrow" );
|
var srcRowId = sourceGrid.getGridParam( "selrow" );
|
||||||
var tgtRowId = targetGrid.getGridParam( "selrow" );
|
var tgtRowId = targetGrid.getGridParam( "selrow" );
|
||||||
@@ -966,7 +969,7 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$("input[name=removeAll]").click(function(){
|
$("#removeAll").click(function(){
|
||||||
var tgtRowId = targetGrid.getGridParam( "selrow" );
|
var tgtRowId = targetGrid.getGridParam( "selrow" );
|
||||||
if (tgtRowId == null) {alert("타겟레이아웃을 선택하여 주십시요.");return;}
|
if (tgtRowId == null) {alert("타겟레이아웃을 선택하여 주십시요.");return;}
|
||||||
//grid data
|
//grid data
|
||||||
@@ -986,6 +989,49 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$("#add").click(function() {
|
||||||
|
|
||||||
|
var srcRowId = sourceGrid.getGridParam( "selrow" );
|
||||||
|
var tgtRowId = targetGrid.getGridParam( "selrow" );
|
||||||
|
if (srcRowId == null) {alert('<%=localeMessage.getString("transformManDetail.alert1")%>');return;}
|
||||||
|
if (tgtRowId == null) {alert('<%=localeMessage.getString("transformManDetail.alert2")%>');return;}
|
||||||
|
|
||||||
|
//field, ATTR 여부 판단
|
||||||
|
var sourceRow = sourceGrid.getRowData( srcRowId );
|
||||||
|
var targetRow = targetGrid.getRowData( tgtRowId );
|
||||||
|
if ( (sourceRow["loutItemType"] == 'Field' || sourceRow["loutItemType"] == 'Attr' || sourceRow["loutItemType"] == 'Array') &&
|
||||||
|
(targetRow["loutItemType"] == 'Field' || targetRow["loutItemType"] == 'Attr' || targetRow["loutItemType"] == 'Array') ){
|
||||||
|
;
|
||||||
|
}else{
|
||||||
|
alert('<%=localeMessage.getString("transformManDetail.alert3")%>');
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
|
||||||
|
targetGrid.jqGrid('setCell',tgtRowId,'CNVSNCMDNAME',addArrayTag(sourceRow['loutItemType'], addGroupTag(srcGroup,sourceRow['LOUTITEMPATH'])));
|
||||||
|
targetGrid.jqGrid('setCell',tgtRowId,'CNVSNRSULTITEMPATHNAME',addArrayTag(targetRow['loutItemType'], addGroupTag(tgtGroup,targetRow['LOUTITEMPATH'])));
|
||||||
|
targetGrid.jqGrid('setCell',tgtRowId,'CNVSNITEMSERNO',targetRow['loutItemSerno']);
|
||||||
|
|
||||||
|
try {
|
||||||
|
jsPlumbConnect(srcRowId, tgtRowId);
|
||||||
|
} catch (e) {console.error(e);}
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#remove").click(function(){
|
||||||
|
var tgtRowId = targetGrid.getGridParam( "selrow" );
|
||||||
|
if (tgtRowId == null) {alert("타겟레이아웃을 선택하여 주십시요.");return;}
|
||||||
|
//grid data
|
||||||
|
var targetData = targetGrid.getRowData();
|
||||||
|
|
||||||
|
targetGrid.jqGrid('setCell', tgtRowId, 'CNVSNCMDNAME', null);
|
||||||
|
targetGrid.jqGrid('setCell', tgtRowId, 'CNVSNRSULTITEMPATHNAME', null);
|
||||||
|
targetGrid.jqGrid('setCell', tgtRowId, 'CNVSNITEMSERNO', null);
|
||||||
|
targetGrid.jqGrid('setCell', tgtRowId, 'CNVSNITEMBASCVAL', null);
|
||||||
|
|
||||||
|
const targetEndpointElementId = targetGrid.getEndpointElementId(tgtRowId);
|
||||||
|
jsPlumbInstance.deleteConnectionsForElement(document.getElementById(targetEndpointElementId));
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
$("textarea[name=CNVSNRSULTITEMPATHNAME],textarea[name=CNVSNCMDNAME],input[name=CNVSNITEMBASCVAL],input[name=CNVSNITEMSERNO]").blur(function(){
|
$("textarea[name=CNVSNRSULTITEMPATHNAME],textarea[name=CNVSNCMDNAME],input[name=CNVSNITEMBASCVAL],input[name=CNVSNITEMSERNO]").blur(function(){
|
||||||
var rowId = targetGrid.getGridParam( "selrow" );
|
var rowId = targetGrid.getGridParam( "selrow" );
|
||||||
if (isNull(rowId)) return;
|
if (isNull(rowId)) return;
|
||||||
@@ -2161,12 +2207,12 @@
|
|||||||
<div id="sourcePage"></div>
|
<div id="sourcePage"></div>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td style="width:30%; text-align:center; vertical-align: top;">
|
<td style="width:30%; min-width:70px; text-align:center; vertical-align: top; ">
|
||||||
|
<button type=button id="remove" name="remove" class="cssbtn btn_move" title="remove"><</button>
|
||||||
<br /><!-- 이 br 이 없을 때 버튼이 제대로 동작 하지 않는다. -->
|
<button type=button id="add" name="add" class="cssbtn btn_move" title="add"> > </button><br />
|
||||||
<input type=button id="removeAll" name="removeAll" class="btn_img btn_removeAll"/><br />
|
<button type=button id="removeAll" name="removeAll" class="cssbtn btn_move" title="remove all"> << </button>
|
||||||
<input type=button id="addAll" name="addAll" class="btn_img btn_addAll"/><br />
|
<button type=button id="addAll" name="addAll" class="cssbtn btn_move" title="add all"> >> </button><br />
|
||||||
<input type=button id="auto" name="auto" class="btn_img btn_auto" />
|
<button type=button id="auto" name="auto" class="cssbtn btn_move" style="width: 70px; " title="auto"> Auto </button>
|
||||||
</td>
|
</td>
|
||||||
<td style="vertical-align:top;">
|
<td style="vertical-align:top;">
|
||||||
<table class="table_row" cellspacing="0">
|
<table class="table_row" cellspacing="0">
|
||||||
|
|||||||
@@ -47,9 +47,6 @@ function init(callback){
|
|||||||
dataType:"json",
|
dataType:"json",
|
||||||
data:{cmd: 'LIST_INIT', codeGroupArr : 'SVC_SAME_TIME_TYPE,<%= tranTypeCode %>'},
|
data:{cmd: 'LIST_INIT', codeGroupArr : 'SVC_SAME_TIME_TYPE,<%= tranTypeCode %>'},
|
||||||
success:function(json){
|
success:function(json){
|
||||||
new makeOptions("CODE","NAME").setObj($("select[name=searchSvcMotivUsedStcd]")).setNoValueInclude(true).setNoValue("", "<%=localeMessage.getString("combo.all")%>").setData(json.list[0].SVC_SAME_TIME_TYPE).rendering();
|
|
||||||
new makeOptions("CODE","NAME").setObj($("select[name=searchPsvintfacdsticName]")).setNoValueInclude(true).setNoValue("", "<%=localeMessage.getString("combo.all")%>").setData(json.list[0].SVC_SAME_TIME_TYPE).rendering();
|
|
||||||
new makeOptions("CODE","NAME").setObj($("select[name=searchFlowControl]")).setNoValueInclude(true).setNoValue("", "<%=localeMessage.getString("combo.all")%>").setData(json.listFlowControl).rendering();
|
|
||||||
new makeOptions("CODE","NAME").setObj($("select[name=searchTranType]")).setNoValueInclude(true).setNoValue("", "<%=localeMessage.getString("combo.all")%>").setData(json.list[0].<%= tranTypeCode %>).rendering();
|
new makeOptions("CODE","NAME").setObj($("select[name=searchTranType]")).setNoValueInclude(true).setNoValue("", "<%=localeMessage.getString("combo.all")%>").setData(json.list[0].<%= tranTypeCode %>).rendering();
|
||||||
svrInst = json.listInoutType;
|
svrInst = json.listInoutType;
|
||||||
putSelectFromParam();
|
putSelectFromParam();
|
||||||
@@ -89,8 +86,6 @@ $(document).ready(function() {
|
|||||||
gridPostData["rmsMenuAuth"]= auth;
|
gridPostData["rmsMenuAuth"]= auth;
|
||||||
|
|
||||||
init(detail);
|
init(detail);
|
||||||
gridPostData["searchSvcMotivUsedStcd"] = '${param.searchSvcMotivUsedStcd}';
|
|
||||||
gridPostData["searchPsvintfacdsticName"] = '${param.searchPsvintfacdsticName}';
|
|
||||||
|
|
||||||
$('#grid').jqGrid({
|
$('#grid').jqGrid({
|
||||||
datatype:"json",
|
datatype:"json",
|
||||||
@@ -100,10 +95,8 @@ $(document).ready(function() {
|
|||||||
colNames:['<%= localeMessage.getString("eaiMsg.bizCode")%> ',
|
colNames:['<%= localeMessage.getString("eaiMsg.bizCode")%> ',
|
||||||
'<%= localeMessage.getString("eaiMessage.eaiSvcName")%> ',
|
'<%= localeMessage.getString("eaiMessage.eaiSvcName")%> ',
|
||||||
'<%= localeMessage.getString("eaiMessage.eaiSvcDesc")%> ',
|
'<%= localeMessage.getString("eaiMessage.eaiSvcDesc")%> ',
|
||||||
'<%= localeMessage.getString("eaiMessage.svcMotivUsedStcd")%>',
|
'<%= localeMessage.getString("eaiMessage.gstatSysAdptr")%>',
|
||||||
'<%= localeMessage.getString("eaiMessage.psvintfacdsticName")%>',
|
'<%= localeMessage.getString("eaiMessage.psvSysAdptr")%>',
|
||||||
'<%= localeMessage.getString("eaiMessage.queueName")%> ',
|
|
||||||
'<%= localeMessage.getString("eaiMessage.flowCtrlRoutName")%> ',
|
|
||||||
'<%= localeMessage.getString("eaiMessage.tranType")%> ',
|
'<%= localeMessage.getString("eaiMessage.tranType")%> ',
|
||||||
'<%= localeMessage.getString("combo.useYn")%> ',
|
'<%= localeMessage.getString("combo.useYn")%> ',
|
||||||
'<%= localeMessage.getString("eaiMessage.sevrDstCd")%>',
|
'<%= localeMessage.getString("eaiMessage.sevrDstCd")%>',
|
||||||
@@ -113,10 +106,8 @@ $(document).ready(function() {
|
|||||||
{ name : 'EAIBZWKDSTCD' , align:'center' ,sortable:false, width:20 },
|
{ name : 'EAIBZWKDSTCD' , align:'center' ,sortable:false, width:20 },
|
||||||
{ name : 'EAISVCNAME' , align:'left', width:50 },
|
{ name : 'EAISVCNAME' , align:'left', width:50 },
|
||||||
{ name : 'EAISVCDESC' , align:'left' },
|
{ name : 'EAISVCDESC' , align:'left' },
|
||||||
{ name : 'SVCMOTIVUSEDSTCD', align:'center', width:50 },
|
{ name : 'GSTATSYSADPTRBZWKGROUPNAME', align:'left', width:80 },
|
||||||
{ name : 'PSVINTFACDSTICNAME', align:'center', width:50 },
|
{ name : 'PSVSYSADPTRBZWKGROUPNAME', align:'left', width:80 },
|
||||||
{ name : 'NONMOTIVROUTURINAME' , align:'left', width:90 },
|
|
||||||
{ name : 'FLOWCTRLROUTNAME' , align:'center', width:40 },
|
|
||||||
{ name : 'TRANTYPE', align:'center', width:30 },
|
{ name : 'TRANTYPE', align:'center', width:30 },
|
||||||
{ name : 'USEYN', align:'center', width:30,editoptions:{value:"0:<%= localeMessage.getString("combo.usen")%>;1:<%= localeMessage.getString("combo.usey")%>"}, formatter:"select"},
|
{ name : 'USEYN', align:'center', width:30,editoptions:{value:"0:<%= localeMessage.getString("combo.usen")%>;1:<%= localeMessage.getString("combo.usey")%>"}, formatter:"select"},
|
||||||
{ name : 'EAISEVRDSTCD', align:'center', width:30 , formatter:formatter, hidden:true},
|
{ name : 'EAISEVRDSTCD', align:'center', width:30 , formatter:formatter, hidden:true},
|
||||||
@@ -426,28 +417,25 @@ function deployInterfaces(ret) {
|
|||||||
<td>
|
<td>
|
||||||
<input type="text" name="searchEaiSvcName" value="${param.searchEaiSvcName}">
|
<input type="text" name="searchEaiSvcName" value="${param.searchEaiSvcName}">
|
||||||
</td>
|
</td>
|
||||||
<th style="width:10%; min-width:120px;"><%= localeMessage.getString("eaiMessage.svcMotivUsedStcd")%></th>
|
|
||||||
<td><div class="select-style"><select name="searchSvcMotivUsedStcd" value="${param.searchSvcMotivUsedStcd}"></select></div></td>
|
|
||||||
<th style="width:10%; min-width:90px;"><%= localeMessage.getString("eaiMessage.tranType")%></th>
|
|
||||||
<td><div class="select-style"><select name="searchTranType" value="${param.searchTranType}"></select></div></td>
|
|
||||||
|
|
||||||
<th style="width:10%; min-width:90px;"><%= localeMessage.getString("eaiMessage.eaiSvcDesc")%></th>
|
<th style="width:10%; min-width:90px;"><%= localeMessage.getString("eaiMessage.eaiSvcDesc")%></th>
|
||||||
<td>
|
<td>
|
||||||
<input type="text" name="searchEaiSvcDesc" value="${param.searchEaiSvcDesc}">
|
<input type="text" name="searchEaiSvcDesc" value="${param.searchEaiSvcDesc}">
|
||||||
</td>
|
</td>
|
||||||
|
<th style="width:10%; min-width:90px;"><%= localeMessage.getString("eaiMessage.tranType")%></th>
|
||||||
|
<td><div class="select-style"><select name="searchTranType" value="${param.searchTranType}"></select></div></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th><%= localeMessage.getString("eaiMessage.searchBzwkDstCd")%></th>
|
<th><%= localeMessage.getString("eaiMessage.searchBzwkDstCd")%></th>
|
||||||
<td>
|
<td>
|
||||||
<input type="text" name="searchEaiBzwkDstcd" value="${param.searchEaiBzwkDstcd}">
|
<input type="text" name="searchEaiBzwkDstcd" value="${param.searchEaiBzwkDstcd}">
|
||||||
</td>
|
</td>
|
||||||
<th><%= localeMessage.getString("eaiMessage.psvintfacdsticName")%></th>
|
<th><%= localeMessage.getString("eaiMessage.gstatSysAdptr")%></th>
|
||||||
<td><div class="select-style"><select name="searchPsvintfacdsticName" value="${param.searchPsvintfacdsticName}"></select></div></td>
|
|
||||||
<th><%= localeMessage.getString("eaiMessage.searchFlowControl")%></th>
|
|
||||||
<td><div class="select-style"><select name="searchFlowControl" value="${param.searchFlowControl}"></select></div></td>
|
|
||||||
<th><%= localeMessage.getString("eaiMessage.queueName")%></th>
|
|
||||||
<td>
|
<td>
|
||||||
<input type="text" name="searchQueueName" value="${param.searchQueueName}">
|
<input type="text" name="searchGstatSysAdptrBzwkGroupName" value="${param.searchGstatSysAdptrBzwkGroupName}">
|
||||||
|
</td>
|
||||||
|
<th><%= localeMessage.getString("eaiMessage.psvSysAdptr")%></th>
|
||||||
|
<td>
|
||||||
|
<input type="text" name="searchPsvSysAdptrBzwkGroupName" value="${param.searchPsvSysAdptrBzwkGroupName}">
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|||||||
@@ -72,13 +72,22 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
function detail(){
|
// 체크박스는 name 을 search* 로 두면 getSearchForJqgrid 가 해제 상태에서도 value 를 담아버린다
|
||||||
|
// (input[type!=radio][name^=search] 를 checked 여부와 무관하게 수집) → 여기서 직접 붙인다
|
||||||
|
function getPopupSearchData() {
|
||||||
var postData = getSearchForJqgrid("cmd","LIST"); //jqgrid에서는 object 로
|
var postData = getSearchForJqgrid("cmd","LIST"); //jqgrid에서는 object 로
|
||||||
|
postData.searchApiSpecYn = $("#chkApiSpec").is(":checked") ? "Y" : "";
|
||||||
|
postData.searchPortalDisplayYn = $("#chkPortalDisplay").is(":checked") ? "Y" : "";
|
||||||
|
return postData;
|
||||||
|
}
|
||||||
|
|
||||||
|
function detail(){
|
||||||
|
var postData = getPopupSearchData();
|
||||||
$("#grid").setGridParam({ url:url,postData: postData }).trigger("reloadGrid");
|
$("#grid").setGridParam({ url:url,postData: postData }).trigger("reloadGrid");
|
||||||
}
|
}
|
||||||
|
|
||||||
function search(){
|
function search(){
|
||||||
var postData = getSearchForJqgrid("cmd","LIST"); //jqgrid에서는 object 로
|
var postData = getPopupSearchData();
|
||||||
$("#grid").setGridParam({ url:url,postData: postData ,page:1 }).trigger("reloadGrid");
|
$("#grid").setGridParam({ url:url,postData: postData ,page:1 }).trigger("reloadGrid");
|
||||||
}
|
}
|
||||||
function ioFormatter(cellvalue,options,rowObject){
|
function ioFormatter(cellvalue,options,rowObject){
|
||||||
@@ -97,7 +106,7 @@
|
|||||||
|
|
||||||
function list(){
|
function list(){
|
||||||
detail()
|
detail()
|
||||||
var gridPostData = getSearchForJqgrid("cmd","LIST"); //jqgrid에서는 object 로
|
var gridPostData = getPopupSearchData();
|
||||||
// gridPostData.searchApiEnableYn = 'Y';
|
// gridPostData.searchApiEnableYn = 'Y';
|
||||||
var urlParams = new URLSearchParams(window.location.search);
|
var urlParams = new URLSearchParams(window.location.search);
|
||||||
var selectedApiIds = urlParams.get("selectedApiIds");
|
var selectedApiIds = urlParams.get("selectedApiIds");
|
||||||
@@ -189,6 +198,9 @@
|
|||||||
$("select[name=searchEaiBzwkDstcd]").change(function() {
|
$("select[name=searchEaiBzwkDstcd]").change(function() {
|
||||||
search();
|
search();
|
||||||
});
|
});
|
||||||
|
$("#chkApiSpec, #chkPortalDisplay").change(function() {
|
||||||
|
search();
|
||||||
|
});
|
||||||
$("#btn_search").click(function(){
|
$("#btn_search").click(function(){
|
||||||
search();
|
search();
|
||||||
});
|
});
|
||||||
@@ -247,6 +259,18 @@
|
|||||||
<input type="text" name="searchApiFullPath" value="${param.searchApiFullPath}">
|
<input type="text" name="searchApiFullPath" value="${param.searchApiFullPath}">
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th style="width:180px;">포탈 노출</th>
|
||||||
|
<td colspan="3">
|
||||||
|
<label class="checkbox-inline">
|
||||||
|
<input type="checkbox" id="chkApiSpec" <c:if test="${param.searchApiSpecYn eq 'Y'}">checked</c:if>> OpenAPI Spec 등록
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<label class="checkbox-inline">
|
||||||
|
<input type="checkbox" id="chkPortalDisplay" <c:if test="${param.searchPortalDisplayYn eq 'Y'}">checked</c:if>> 포탈 게시
|
||||||
|
</label>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<table id="grid" ></table>
|
<table id="grid" ></table>
|
||||||
|
|||||||
@@ -264,6 +264,16 @@
|
|||||||
|
|
||||||
$("#clientName").text(data.clientName);
|
$("#clientName").text(data.clientName);
|
||||||
|
|
||||||
|
// 신청 사유. 해지 신청은 사유 입력이 필수이므로 "해지 사유"로 표기하고, 그 외 유형은 "신청 사유"
|
||||||
|
if (data.requestReason) {
|
||||||
|
$("#requestReasonLabel").text(data.requestType === 'DELETE' ? "해지 사유" : "신청 사유");
|
||||||
|
$("#requestReason").text(data.requestReason);
|
||||||
|
$("#requestReasonRow").show();
|
||||||
|
} else {
|
||||||
|
$("#requestReason").text("");
|
||||||
|
$("#requestReasonRow").hide();
|
||||||
|
}
|
||||||
|
|
||||||
var apiServiceHtml = "";
|
var apiServiceHtml = "";
|
||||||
for (var i = 0; i < data.apiServices.length; i++) {
|
for (var i = 0; i < data.apiServices.length; i++) {
|
||||||
var apiService = data.apiServices[i];
|
var apiService = data.apiServices[i];
|
||||||
@@ -365,6 +375,10 @@
|
|||||||
<th style="width:20%;">이름</th>
|
<th style="width:20%;">이름</th>
|
||||||
<td><span id="clientName"></span></td>
|
<td><span id="clientName"></span></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr id="requestReasonRow" style="display:none;">
|
||||||
|
<th style="width:20%;"><span id="requestReasonLabel">신청 사유</span></th>
|
||||||
|
<td><span id="requestReason" style="white-space: pre-wrap;"></span></td>
|
||||||
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
<div class="title">API 목록</div>
|
<div class="title">API 목록</div>
|
||||||
<table id="apisTable" class="table_row" cellspacing="0">
|
<table id="apisTable" class="table_row" cellspacing="0">
|
||||||
|
|||||||
@@ -189,7 +189,7 @@
|
|||||||
<td>
|
<td>
|
||||||
<input type="text" id="keywordList" style="width:100%" placeholder="쉼표(,)로 구분하여 입력">
|
<input type="text" id="keywordList" style="width:100%" placeholder="쉼표(,)로 구분하여 입력">
|
||||||
<div class="help-text" style="color:#666; font-size:12px; margin-top:5px;">
|
<div class="help-text" style="color:#666; font-size:12px; margin-top:5px;">
|
||||||
예시: #인증, #대출, #예금
|
예시: 인증, 대출, 예금
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@@ -327,14 +327,61 @@
|
|||||||
}, 'json').fail(ajaxFail);
|
}, 'json').fail(ajaxFail);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ── 캐시 Reload ──
|
||||||
|
var reloadModal;
|
||||||
|
var reloadBtnHtml;
|
||||||
|
|
||||||
function reloadPortalCache() {
|
function reloadPortalCache() {
|
||||||
|
var $btn = $('#btnReloadCache');
|
||||||
|
if ($btn.prop('disabled')) return;
|
||||||
|
if (reloadBtnHtml === undefined) reloadBtnHtml = $btn.html();
|
||||||
|
$btn.prop('disabled', true)
|
||||||
|
.html('<span class="spinner-border spinner-border-sm"></span> 리로드 중...');
|
||||||
|
|
||||||
$.post(url, { cmd: 'TRANSACTION_RELOAD' }, function (result) {
|
$.post(url, { cmd: 'TRANSACTION_RELOAD' }, function (result) {
|
||||||
if (result && result.success) {
|
showReloadResult(result);
|
||||||
alert('포탈 메뉴 캐시 리로드 완료 (항목 ' + result.itemCount + '건, ' + result.reloadedAt + ')');
|
}, 'json').fail(ajaxFail).always(function () {
|
||||||
} else {
|
$btn.prop('disabled', false).html(reloadBtnHtml);
|
||||||
alert('캐시 리로드 실패: ' + (result ? result.message : '알 수 없는 오류'));
|
});
|
||||||
}
|
}
|
||||||
}, 'json').fail(ajaxFail);
|
|
||||||
|
function showReloadResult(result) {
|
||||||
|
if (!result) {
|
||||||
|
alert('캐시 리로드 실패: 알 수 없는 오류');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var servers = result.servers || [];
|
||||||
|
var $summary = $('#reloadSummary');
|
||||||
|
$summary.removeClass('alert-success alert-danger alert-warning')
|
||||||
|
.addClass(result.success ? 'alert-success'
|
||||||
|
: (result.successCount > 0 ? 'alert-warning' : 'alert-danger'))
|
||||||
|
.text(result.message || '');
|
||||||
|
|
||||||
|
var rows = '';
|
||||||
|
servers.forEach(function (s) {
|
||||||
|
var badge = s.success
|
||||||
|
? '<span class="badge text-bg-success">성공</span>'
|
||||||
|
: '<span class="badge text-bg-danger">실패</span>';
|
||||||
|
var detail = s.success
|
||||||
|
? ('항목 ' + (s.itemCount == null ? '-' : s.itemCount) + '건'
|
||||||
|
+ (s.reloadedAt ? ' / ' + escapeHtml(String(s.reloadedAt)) : ''))
|
||||||
|
: escapeHtml(String(s.message || '-'));
|
||||||
|
rows += '<tr>'
|
||||||
|
+ '<td class="text-center">' + badge + '</td>'
|
||||||
|
+ '<td style="word-break:break-all;">' + escapeHtml(String(s.url || '')) + '</td>'
|
||||||
|
+ '<td>' + detail + '</td>'
|
||||||
|
+ '<td class="text-end">' + (s.elapsedMs == null ? '-' : s.elapsedMs + 'ms') + '</td>'
|
||||||
|
+ '</tr>';
|
||||||
|
});
|
||||||
|
if (rows === '') {
|
||||||
|
rows = '<tr><td colspan="4" class="text-center text-muted">'
|
||||||
|
+ '호출 대상 서버가 없습니다. 아래 설정 안내를 확인하세요.</td></tr>';
|
||||||
|
}
|
||||||
|
$('#reloadResultBody').html(rows);
|
||||||
|
|
||||||
|
if (!reloadModal) reloadModal = new bootstrap.Modal(document.getElementById('reloadResultModal'));
|
||||||
|
reloadModal.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
function ajaxFail(xhr) {
|
function ajaxFail(xhr) {
|
||||||
@@ -453,7 +500,7 @@
|
|||||||
<button type="button" class="btn btn-sm btn-outline-danger" level="W" onclick="initializeMenus()">
|
<button type="button" class="btn btn-sm btn-outline-danger" level="W" onclick="initializeMenus()">
|
||||||
<i class="bi bi-arrow-counterclockwise"></i> 메뉴 초기화</button>
|
<i class="bi bi-arrow-counterclockwise"></i> 메뉴 초기화</button>
|
||||||
<span class="spacer"></span>
|
<span class="spacer"></span>
|
||||||
<button type="button" class="btn btn-sm btn-outline-secondary" level="W" onclick="reloadPortalCache()">
|
<button type="button" class="btn btn-sm btn-outline-secondary" id="btnReloadCache" level="W" onclick="reloadPortalCache()">
|
||||||
<i class="bi bi-arrow-repeat"></i> 캐시 Reload</button>
|
<i class="bi bi-arrow-repeat"></i> 캐시 Reload</button>
|
||||||
<button type="button" class="btn btn-sm btn-success" level="W" onclick="savePlacements()">
|
<button type="button" class="btn btn-sm btn-success" level="W" onclick="savePlacements()">
|
||||||
<i class="bi bi-save"></i> 저장</button>
|
<i class="bi bi-save"></i> 저장</button>
|
||||||
@@ -463,6 +510,12 @@
|
|||||||
드래그로 위치를 조절한 뒤 <strong>저장</strong> 버튼으로 일괄 반영합니다.
|
드래그로 위치를 조절한 뒤 <strong>저장</strong> 버튼으로 일괄 반영합니다.
|
||||||
기본 항목([기본] 배지)은 [-] 시 <strong>미배치</strong>로만 이동하고, 커스텀 항목은 미배치 시 <strong>삭제</strong>됩니다.
|
기본 항목([기본] 배지)은 [-] 시 <strong>미배치</strong>로만 이동하고, 커스텀 항목은 미배치 시 <strong>삭제</strong>됩니다.
|
||||||
저장 후 <strong>캐시 Reload</strong> 를 실행해야 포탈에 즉시 반영됩니다(미실행 시 TTL 경과 후 반영).
|
저장 후 <strong>캐시 Reload</strong> 를 실행해야 포탈에 즉시 반영됩니다(미실행 시 TTL 경과 후 반영).
|
||||||
|
<br>
|
||||||
|
캐시 Reload 대상 서버는 포탈 프로퍼티 <code>Portal / portal.internal.menu-reload-url</code> 로 설정합니다.
|
||||||
|
포탈이 <strong>다중 서버(이중화)</strong> 로 기동된 경우 모든 서버의 리로드 URL 을
|
||||||
|
<strong>콤마(,) 또는 줄바꿈</strong> 으로 나열해야 전체 서버에 반영됩니다
|
||||||
|
(예: <code>http://10.0.0.11:39130/internal/menu/reload, http://10.0.0.12:39130/internal/menu/reload</code>).
|
||||||
|
서버별 요청 타임아웃은 <strong>3초</strong> 이며, 실행 결과는 서버별로 표시됩니다.
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="menu-board">
|
<div class="menu-board">
|
||||||
@@ -544,6 +597,39 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- 캐시 Reload 결과 -->
|
||||||
|
<div class="modal fade" id="reloadResultModal" tabindex="-1" aria-hidden="true">
|
||||||
|
<div class="modal-dialog modal-lg">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title">포탈 메뉴 캐시 Reload 결과</h5>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="닫기"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="alert py-2 px-3" id="reloadSummary" style="font-size:13px;"></div>
|
||||||
|
<table class="table table-sm table-bordered align-middle" style="font-size:12px;">
|
||||||
|
<thead class="table-light">
|
||||||
|
<tr>
|
||||||
|
<th style="width:70px;" class="text-center">결과</th>
|
||||||
|
<th>서버 URL</th>
|
||||||
|
<th style="width:38%;">상세</th>
|
||||||
|
<th style="width:80px;" class="text-end">소요</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody id="reloadResultBody"></tbody>
|
||||||
|
</table>
|
||||||
|
<div class="text-muted" style="font-size:12px;">
|
||||||
|
대상 서버는 포탈 프로퍼티 <code>Portal / portal.internal.menu-reload-url</code> 에
|
||||||
|
콤마(,) 또는 줄바꿈으로 나열합니다. 서버별 타임아웃 3초, 전 서버 병렬 호출입니다.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-sm btn-secondary" data-bs-dismiss="modal">닫기</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div><!-- end content_middle -->
|
</div><!-- end content_middle -->
|
||||||
</div><!-- end right_box -->
|
</div><!-- end right_box -->
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@@ -189,8 +189,11 @@
|
|||||||
// AuthorizeInterceptor 가 정상적으로 권한 인식. window.open 직접 호출 시 권한 부족 발생.
|
// AuthorizeInterceptor 가 정상적으로 권한 인식. window.open 직접 호출 시 권한 부족 발생.
|
||||||
// 본 페이지는 summernote 본문 에디터 등 다른 iframe 이 함께 존재할 수 있어
|
// 본 페이지는 summernote 본문 에디터 등 다른 iframe 이 함께 존재할 수 있어
|
||||||
// frames[0] 가정은 위험 → DOM 에서 .ui-dialog 내 iframe 중 src=apiGroupMan 인 것을 식별.
|
// frames[0] 가정은 위험 → DOM 에서 .ui-dialog 내 iframe 중 src=apiGroupMan 인 것을 식별.
|
||||||
|
// 공지 영향 API 는 포탈에 실제 노출되는 것만 고르면 되므로 두 조건을 켠 채로 연다.
|
||||||
|
// (타 화면에서 여는 팝업은 파라미터가 없어 해제 상태 — 팝업 기본값은 건드리지 않는다)
|
||||||
var selectedIds = affectedApis.map(function(a) { return a.apiId; }).join(',');
|
var selectedIds = affectedApis.map(function(a) { return a.apiId; }).join(',');
|
||||||
var url2 = apiPopupUrl + '?cmd=POPUP&selectedApiIds=' + encodeURIComponent(selectedIds);
|
var url2 = apiPopupUrl + '?cmd=POPUP&searchApiSpecYn=Y&searchPortalDisplayYn=Y'
|
||||||
|
+ '&selectedApiIds=' + encodeURIComponent(selectedIds);
|
||||||
var args = {};
|
var args = {};
|
||||||
showModal(url2, args, 1280, 860, function () {
|
showModal(url2, args, 1280, 860, function () {
|
||||||
var doc = args.self && args.self.document;
|
var doc = args.self && args.self.document;
|
||||||
|
|||||||
@@ -40,7 +40,7 @@
|
|||||||
if ($('input[name=prptyName]').val() == "") {
|
if ($('input[name=prptyName]').val() == "") {
|
||||||
alert("<%= localeMessage.getString("propertyDetail.checkRequired2") %>");
|
alert("<%= localeMessage.getString("propertyDetail.checkRequired2") %>");
|
||||||
return false;
|
return false;
|
||||||
} else if ($('input[name=prpty2Val]').val() == "") {
|
} else if ($('[name=prpty2Val]').val() == "") {
|
||||||
alert("<%= localeMessage.getString("propertyDetail.checkRequired3") %>");
|
alert("<%= localeMessage.getString("propertyDetail.checkRequired3") %>");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -90,7 +90,19 @@
|
|||||||
'설명',
|
'설명',
|
||||||
'<%= localeMessage.getString("propertyDetail.delYn") %>'],
|
'<%= localeMessage.getString("propertyDetail.delYn") %>'],
|
||||||
colModel: [{name: 'PRPTYNAME', width: 50, align: 'left', editable: true},
|
colModel: [{name: 'PRPTYNAME', width: 50, align: 'left', editable: true},
|
||||||
{name: 'PRPTY2VAL', width: 150, align: 'left', editable: true},
|
{
|
||||||
|
name: 'PRPTY2VAL',
|
||||||
|
width: 150,
|
||||||
|
align: 'left',
|
||||||
|
editable: true,
|
||||||
|
//다행(멀티라인) 값 편집 — 관련 사이트 목록처럼 줄 단위 표기하는 값 지원
|
||||||
|
edittype: 'textarea',
|
||||||
|
editoptions: {rows: 3, cols: 60},
|
||||||
|
//줄바꿈이 그리드에서도 그대로 보이도록
|
||||||
|
cellattr: function () {
|
||||||
|
return ' style="white-space:pre-line; word-break:break-all;"';
|
||||||
|
}
|
||||||
|
},
|
||||||
{name: 'PRPTYDESC', width: 200, align: 'left', editable: true, edittype: 'textarea', editoptions: {rows: 2}},
|
{name: 'PRPTYDESC', width: 200, align: 'left', editable: true, edittype: 'textarea', editoptions: {rows: 2}},
|
||||||
{
|
{
|
||||||
name: 'DELETEYN',
|
name: 'DELETEYN',
|
||||||
@@ -265,7 +277,7 @@
|
|||||||
}
|
}
|
||||||
var data = new Object();
|
var data = new Object();
|
||||||
data["PRPTYNAME"] = $("input[name=prptyName]").val();
|
data["PRPTYNAME"] = $("input[name=prptyName]").val();
|
||||||
data["PRPTY2VAL"] = $("input[name=prpty2Val]").val();
|
data["PRPTY2VAL"] = $("[name=prpty2Val]").val();
|
||||||
data["PRPTYDESC"] = $("input[name=prptyDesc]").val();
|
data["PRPTYDESC"] = $("input[name=prptyDesc]").val();
|
||||||
|
|
||||||
var rows = $("#grid")[0].rows;
|
var rows = $("#grid")[0].rows;
|
||||||
@@ -346,7 +358,8 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<th><%= localeMessage.getString("propertyDetail.propertyValue") %>
|
<th><%= localeMessage.getString("propertyDetail.propertyValue") %>
|
||||||
</th>
|
</th>
|
||||||
<td colspan="3"><input type="text" name="prpty2Val"/>
|
<td colspan="3"><textarea name="prpty2Val" rows="3"
|
||||||
|
style="width:100%; box-sizing:border-box; resize:vertical;"></textarea>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
|||||||
@@ -222,63 +222,6 @@
|
|||||||
$("input[name=searchEndHHMM]").val(endHHMM);
|
$("input[name=searchEndHHMM]").val(endHHMM);
|
||||||
}
|
}
|
||||||
|
|
||||||
function guidEvent() {
|
|
||||||
var searchGuid = $("input[name=searchGuid]").val();
|
|
||||||
if (searchGuid.trim() == '')
|
|
||||||
return;
|
|
||||||
|
|
||||||
var searchTm = searchGuid.trim();
|
|
||||||
/*
|
|
||||||
var yy = searchTm.substr(13,4);
|
|
||||||
var mm = searchTm.substr(17,2);
|
|
||||||
var dd = searchTm.substr(19,2);
|
|
||||||
var hh = searchTm.substr(21,2);
|
|
||||||
var MM = searchTm.substr(23,2);
|
|
||||||
*/
|
|
||||||
var yy = searchTm.substr(3,4);
|
|
||||||
var mm = searchTm.substr(7,2);
|
|
||||||
var dd = searchTm.substr(9,2);
|
|
||||||
var hh = searchTm.substr(11,2);
|
|
||||||
var MM = searchTm.substr(13,2);
|
|
||||||
|
|
||||||
var ms = Date.UTC(yy,mm-1,dd,hh,MM,00);
|
|
||||||
var date = new Date(ms);
|
|
||||||
var startYYYYMMDD;
|
|
||||||
var startHHMM;
|
|
||||||
var endYYYYMMDD;
|
|
||||||
var endHHMM;
|
|
||||||
//Local Time Setting
|
|
||||||
date.setHours(date.getHours() - 9);
|
|
||||||
//5분 간격
|
|
||||||
date.setMinutes(date.getMinutes() - 5);
|
|
||||||
|
|
||||||
startYYYYMMDD = date.getFullYear() + right("0" + (date.getMonth() + 1), 2) + right("0" + (date.getDate()), 2);
|
|
||||||
startHHMM = right("0" + date.getHours(), 2) + right("0" + date.getMinutes(), 2) + "00";
|
|
||||||
|
|
||||||
date.setMinutes(date.getMinutes() + 10);
|
|
||||||
|
|
||||||
endYYYYMMDD = date.getFullYear() + right("0" + (date.getMonth() + 1), 2) + right("0" + (date.getDate()), 2);
|
|
||||||
endHHMM = right("0" + date.getHours(), 2) + right("0" + date.getMinutes(), 2) + "00";
|
|
||||||
|
|
||||||
//추가 코드 입력 2012.05.16 권세환 (일자가 바뀔경우 시간 간격을 +-5분 -> +-1분)
|
|
||||||
if (startYYYYMMDD.substr(6, 2) != endYYYYMMDD.substr(6, 2)) {
|
|
||||||
date.setMinutes(date.getMinutes() - 6);
|
|
||||||
|
|
||||||
startYYYYMMDD = date.getFullYear() + right("0" + (date.getMonth() + 1), 2) + right("0" + (date.getDate()), 2);
|
|
||||||
startHHMM = right("0" + date.getHours(), 2) + right("0" + date.getMinutes(), 2) + "00";
|
|
||||||
|
|
||||||
date.setMinutes(date.getMinutes() + 2);
|
|
||||||
|
|
||||||
endYYYYMMDD = date.getFullYear() + right("0" + (date.getMonth() + 1), 2) + right("0" + (date.getDate()), 2);
|
|
||||||
endHHMM = right("0" + date.getHours(), 2) + right("0" + date.getMinutes(), 2) + "00";
|
|
||||||
}
|
|
||||||
$("input[name=searchStartYYYYMMDD]").val(startYYYYMMDD);
|
|
||||||
$("input[name=searchEndYYYYMMDD]").val(endYYYYMMDD);
|
|
||||||
$("input[name=searchStartHHMM]").val(startHHMM);
|
|
||||||
$("input[name=searchEndHHMM]").val(endHHMM);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function timeStampFormat2(cellvalue, options, rowObject) {
|
function timeStampFormat2(cellvalue, options, rowObject) {
|
||||||
if (cellvalue == null || cellvalue.length < 17)
|
if (cellvalue == null || cellvalue.length < 17)
|
||||||
return '';
|
return '';
|
||||||
@@ -481,7 +424,6 @@
|
|||||||
//$("#grid").jqGrid('setFrozenColumns');
|
//$("#grid").jqGrid('setFrozenColumns');
|
||||||
|
|
||||||
$("#btn_search").click(function () {
|
$("#btn_search").click(function () {
|
||||||
$("input[name=searchGuid]").blur();
|
|
||||||
detail();
|
detail();
|
||||||
getTransactionCounts();
|
getTransactionCounts();
|
||||||
});
|
});
|
||||||
@@ -551,12 +493,6 @@
|
|||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
//GUID
|
|
||||||
$("input[name=searchGuid]").blur(function (event) {
|
|
||||||
guidEvent();
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
buttonControl();
|
buttonControl();
|
||||||
|
|
||||||
var local = localStorage.getItem("guid");
|
var local = localStorage.getItem("guid");
|
||||||
@@ -701,7 +637,7 @@
|
|||||||
<td colspan="3"><input type="text" name="searchEaiSvcSerno" value="${param.searchEaiSvcSerno}"></td>
|
<td colspan="3"><input type="text" name="searchEaiSvcSerno" value="${param.searchEaiSvcSerno}"></td>
|
||||||
|
|
||||||
<th><%=localeMessage.getString("tracking.keymgtmsgctnt")%></th>
|
<th><%=localeMessage.getString("tracking.keymgtmsgctnt")%></th>
|
||||||
<td colspan="2"><input type="text" name="searchKeyMgtMsgCtnt" value="${param.searchKeyMgtMsgCtnt}"></td>
|
<td colspan="2"><input type="text" name="searchGuid" value="${param.searchGuid}" ></td>
|
||||||
|
|
||||||
<%-- <th><%=localeMessage.getString("tracking.orgGUID")%></th>
|
<%-- <th><%=localeMessage.getString("tracking.orgGUID")%></th>
|
||||||
<td colspan="4"><input type="text" name="searchGuid" value="" maxlength="<%=DbTrackingService.GUID_LENGTH%>"></td> --%>
|
<td colspan="4"><input type="text" name="searchGuid" value="" maxlength="<%=DbTrackingService.GUID_LENGTH%>"></td> --%>
|
||||||
|
|||||||
@@ -376,7 +376,7 @@
|
|||||||
const value = bodyCodeEditor.getValue();
|
const value = bodyCodeEditor.getValue();
|
||||||
let prettyValue = value;
|
let prettyValue = value;
|
||||||
if(syntax === 'JSN'){
|
if(syntax === 'JSN'){
|
||||||
prettyValue = vkbeautify.json(value);
|
prettyValue = preserveExponential(value); //vkbeautify.json(value);
|
||||||
}else if(syntax === 'XML'){
|
}else if(syntax === 'XML'){
|
||||||
prettyValue = vkbeautify.xml(value).trim();
|
prettyValue = vkbeautify.xml(value).trim();
|
||||||
}
|
}
|
||||||
@@ -407,6 +407,19 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
function preserveExponential(jsonString) {
|
||||||
|
// 1. 지수 형태의 숫자(예: 1e+21, 5.43e-7)를 찾아 문자열 ""로 감쌉니다.
|
||||||
|
// JSON의 key 뒤에 오는 value 위치의 지수 표기법을 매칭합니다.
|
||||||
|
let protectedJson = jsonString.replace(/:\s*([+-]?\d+\.?\d*e[+-]?\d+)/gi, ': "$1"');
|
||||||
|
|
||||||
|
// 2. 보호된 상태로 vkbeautify를 실행하여 예쁘게 정렬합니다.
|
||||||
|
let prettyJson = vkbeautify.json(protectedJson);
|
||||||
|
|
||||||
|
// 3. (선택사항) 만약 최종 결과물에서 반드시 큰따옴표("")를 다시 제거해야 한다면 아래 주석을 해제하세요.
|
||||||
|
prettyJson = prettyJson.replace(/:\s*"([+-]?\d+\.?\d*e[+-]?\d+)"/gi, ': $1');
|
||||||
|
|
||||||
|
return prettyJson;
|
||||||
|
}
|
||||||
function doChangeSyntax(syntax){
|
function doChangeSyntax(syntax){
|
||||||
if(syntax === 'JSN'){
|
if(syntax === 'JSN'){
|
||||||
$('#btn_pretty_body').css('display', 'block');
|
$('#btn_pretty_body').css('display', 'block');
|
||||||
|
|||||||
@@ -0,0 +1,343 @@
|
|||||||
|
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %><%@
|
||||||
|
page import="org.quartz.*,
|
||||||
|
org.quartz.impl.matchers.GroupMatcher,
|
||||||
|
org.springframework.web.context.WebApplicationContext,
|
||||||
|
org.springframework.web.context.support.WebApplicationContextUtils,
|
||||||
|
java.util.*,
|
||||||
|
java.text.SimpleDateFormat"
|
||||||
|
%><%!
|
||||||
|
private String fmt(Date date) {
|
||||||
|
if (date == null) return "-";
|
||||||
|
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String relative(Date date) {
|
||||||
|
if (date == null) return "";
|
||||||
|
long diff = date.getTime() - System.currentTimeMillis();
|
||||||
|
String prefix = diff >= 0 ? "+" : "-";
|
||||||
|
long abs = Math.abs(diff) / 1000;
|
||||||
|
if (abs < 60) return prefix + abs + "s";
|
||||||
|
if (abs < 3600) return prefix + (abs / 60) + "m " + (abs % 60) + "s";
|
||||||
|
return prefix + (abs / 3600) + "h " + ((abs % 3600) / 60) + "m";
|
||||||
|
}
|
||||||
|
|
||||||
|
private String stateClass(Trigger.TriggerState state) {
|
||||||
|
if (state == Trigger.TriggerState.NORMAL) return "state-normal";
|
||||||
|
if (state == Trigger.TriggerState.PAUSED) return "state-paused";
|
||||||
|
if (state == Trigger.TriggerState.BLOCKED) return "state-blocked";
|
||||||
|
if (state == Trigger.TriggerState.ERROR) return "state-error";
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, Object> buildTriggerInfo(Scheduler scheduler, Trigger trigger) throws Exception {
|
||||||
|
Map<String, Object> info = new LinkedHashMap<>();
|
||||||
|
Trigger.TriggerState state = scheduler.getTriggerState(trigger.getKey());
|
||||||
|
info.put("triggerName", trigger.getKey().getName());
|
||||||
|
info.put("triggerGroup", trigger.getKey().getGroup());
|
||||||
|
info.put("state", state.name());
|
||||||
|
info.put("stateClass", stateClass(state));
|
||||||
|
info.put("prevFire", fmt(trigger.getPreviousFireTime()));
|
||||||
|
info.put("prevFireRel", relative(trigger.getPreviousFireTime()));
|
||||||
|
info.put("nextFire", fmt(trigger.getNextFireTime()));
|
||||||
|
info.put("nextFireRel", relative(trigger.getNextFireTime()));
|
||||||
|
info.put("priority", trigger.getPriority());
|
||||||
|
if (trigger instanceof CronTrigger) {
|
||||||
|
info.put("type", "Cron");
|
||||||
|
info.put("cronExp", ((CronTrigger) trigger).getCronExpression());
|
||||||
|
} else if (trigger instanceof SimpleTrigger) {
|
||||||
|
SimpleTrigger st = (SimpleTrigger) trigger;
|
||||||
|
info.put("type", "Simple");
|
||||||
|
info.put("cronExp", "interval=" + st.getRepeatInterval() + "ms, repeat=" +
|
||||||
|
(st.getRepeatCount() == SimpleTrigger.REPEAT_INDEFINITELY ? "INF" : st.getRepeatCount()));
|
||||||
|
} else {
|
||||||
|
info.put("type", trigger.getClass().getSimpleName());
|
||||||
|
info.put("cronExp", "-");
|
||||||
|
}
|
||||||
|
if (trigger.getStartTime() != null) info.put("startTime", fmt(trigger.getStartTime()));
|
||||||
|
if (trigger.getEndTime() != null) info.put("endTime", fmt(trigger.getEndTime()));
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Map<String, Object>> getJobList(Scheduler scheduler) throws Exception {
|
||||||
|
List<Map<String, Object>> jobs = new ArrayList<>();
|
||||||
|
for (String group : scheduler.getJobGroupNames()) {
|
||||||
|
for (JobKey jobKey : scheduler.getJobKeys(GroupMatcher.jobGroupEquals(group))) {
|
||||||
|
JobDetail detail = scheduler.getJobDetail(jobKey);
|
||||||
|
List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
|
||||||
|
|
||||||
|
Map<String, Object> job = new LinkedHashMap<>();
|
||||||
|
job.put("name", jobKey.getName());
|
||||||
|
job.put("group", jobKey.getGroup());
|
||||||
|
job.put("jobClass", detail.getJobClass().getSimpleName());
|
||||||
|
job.put("disallowConcurrent", detail.isConcurrentExectionDisallowed());
|
||||||
|
|
||||||
|
StringBuilder dataStr = new StringBuilder();
|
||||||
|
for (String key : detail.getJobDataMap().getKeys()) {
|
||||||
|
if (dataStr.length() > 0) dataStr.append(", ");
|
||||||
|
dataStr.append(key).append("=").append(detail.getJobDataMap().getString(key));
|
||||||
|
}
|
||||||
|
job.put("jobData", dataStr.toString());
|
||||||
|
job.put("triggerCount", triggers.size());
|
||||||
|
|
||||||
|
List<Map<String, Object>> triggerList = new ArrayList<>();
|
||||||
|
for (Trigger trigger : triggers) {
|
||||||
|
triggerList.add(buildTriggerInfo(scheduler, trigger));
|
||||||
|
}
|
||||||
|
job.put("triggerList", triggerList);
|
||||||
|
|
||||||
|
if (!triggers.isEmpty()) {
|
||||||
|
Trigger trigger = triggers.get(0);
|
||||||
|
Trigger.TriggerState state = scheduler.getTriggerState(trigger.getKey());
|
||||||
|
job.put("state", state.name());
|
||||||
|
job.put("stateClass", stateClass(state));
|
||||||
|
job.put("prevFire", fmt(trigger.getPreviousFireTime()));
|
||||||
|
job.put("prevFireRel", relative(trigger.getPreviousFireTime()));
|
||||||
|
job.put("nextFire", fmt(trigger.getNextFireTime()));
|
||||||
|
job.put("nextFireRel", relative(trigger.getNextFireTime()));
|
||||||
|
if (trigger instanceof CronTrigger) {
|
||||||
|
job.put("cronExp", ((CronTrigger) trigger).getCronExpression());
|
||||||
|
} else {
|
||||||
|
job.put("cronExp", "-");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
job.put("state", "NO_TRIGGER");
|
||||||
|
job.put("stateClass", "state-error");
|
||||||
|
job.put("prevFire", "-");
|
||||||
|
job.put("prevFireRel", "");
|
||||||
|
job.put("nextFire", "-");
|
||||||
|
job.put("nextFireRel", "");
|
||||||
|
job.put("cronExp", "-");
|
||||||
|
}
|
||||||
|
jobs.add(job);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
jobs.sort(Comparator.comparing(m -> (String) m.get("name")));
|
||||||
|
return jobs;
|
||||||
|
}
|
||||||
|
%><%
|
||||||
|
WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(application);
|
||||||
|
|
||||||
|
Scheduler scheduler = null;
|
||||||
|
Scheduler clusteredScheduler = null;
|
||||||
|
String error = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
scheduler = (Scheduler) ctx.getBean("scheduler");
|
||||||
|
} catch (Exception e) {
|
||||||
|
error = "scheduler bean not found: " + e.getMessage();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
clusteredScheduler = (Scheduler) ctx.getBean("clusteredScheduler");
|
||||||
|
} catch (Exception e) {
|
||||||
|
// clusteredScheduler is optional
|
||||||
|
}
|
||||||
|
|
||||||
|
// 자동 새로고침 간격 (초), 기본 10초
|
||||||
|
String refreshParam = request.getParameter("refresh");
|
||||||
|
int refreshSec = 10;
|
||||||
|
if (refreshParam != null) {
|
||||||
|
try { refreshSec = Integer.parseInt(refreshParam); } catch (NumberFormatException e) { /* ignore */ }
|
||||||
|
if (refreshSec < 1) refreshSec = 1;
|
||||||
|
}
|
||||||
|
boolean autoRefresh = refreshParam != null;
|
||||||
|
%>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<% if (autoRefresh) { %>
|
||||||
|
<meta http-equiv="refresh" content="<%= refreshSec %>;url=quartzStatus.jsp?refresh=<%= refreshSec %>">
|
||||||
|
<% } %>
|
||||||
|
<title>Quartz Scheduler Status</title>
|
||||||
|
<style>
|
||||||
|
body { font-family: 'Segoe UI', Arial, sans-serif; margin: 20px; background: #f5f5f5; color: #333; }
|
||||||
|
h1 { font-size: 20px; margin-bottom: 5px; }
|
||||||
|
h2 { font-size: 16px; color: #555; margin: 20px 0 8px 0; border-bottom: 2px solid #ddd; padding-bottom: 4px; }
|
||||||
|
.info { font-size: 13px; color: #666; margin-bottom: 15px; }
|
||||||
|
table { width: 100%%; border-collapse: collapse; font-size: 13px; background: #fff; box-shadow: 0 1px 3px rgba(0,0,0,0.1); margin-bottom: 20px; }
|
||||||
|
th { background: #4a5568; color: #fff; padding: 8px 10px; text-align: left; font-weight: 500; }
|
||||||
|
td { padding: 7px 10px; border-bottom: 1px solid #eee; }
|
||||||
|
tr:hover td { background: #f7fafc; }
|
||||||
|
.state-normal { color: #38a169; font-weight: bold; }
|
||||||
|
.state-paused { color: #d69e2e; font-weight: bold; }
|
||||||
|
.state-blocked { color: #e53e3e; font-weight: bold; }
|
||||||
|
.state-error { color: #e53e3e; font-weight: bold; }
|
||||||
|
.mono { font-family: 'Consolas', 'Monaco', monospace; font-size: 12px; }
|
||||||
|
.rel { color: #718096; font-size: 11px; margin-left: 4px; }
|
||||||
|
.badge { display: inline-block; padding: 2px 6px; border-radius: 3px; font-size: 11px; }
|
||||||
|
.badge-yes { background: #c6f6d5; color: #276749; }
|
||||||
|
.badge-no { background: #fed7d7; color: #9b2c2c; }
|
||||||
|
.scheduler-meta { display: flex; gap: 20px; flex-wrap: wrap; margin-bottom: 10px; }
|
||||||
|
.scheduler-meta span { font-size: 13px; }
|
||||||
|
.scheduler-meta strong { color: #4a5568; }
|
||||||
|
.error { color: #e53e3e; padding: 10px; background: #fff5f5; border: 1px solid #fc8181; border-radius: 4px; }
|
||||||
|
.toolbar { font-size: 12px; color: #718096; }
|
||||||
|
.toolbar a { color: #4299e1; text-decoration: none; margin: 0 4px; }
|
||||||
|
.toolbar a:hover { text-decoration: underline; }
|
||||||
|
.toolbar .active { font-weight: bold; color: #2b6cb0; background: #ebf4ff; padding: 2px 6px; border-radius: 3px; }
|
||||||
|
.auto-badge { display: inline-block; padding: 1px 6px; border-radius: 3px; font-size: 11px; background: #bee3f8; color: #2a4365; margin-left: 6px; }
|
||||||
|
.trigger-toggle { cursor: pointer; user-select: none; }
|
||||||
|
.trigger-toggle:hover td { background: #edf2f7; }
|
||||||
|
.trigger-row { display: none; }
|
||||||
|
.trigger-row.open { display: table-row; }
|
||||||
|
.trigger-row td { background: #f7fafc; padding: 5px 10px 5px 30px; border-bottom: 1px solid #e2e8f0; font-size: 12px; }
|
||||||
|
.trigger-detail-table { width: 100%; border-collapse: collapse; font-size: 12px; margin: 0; }
|
||||||
|
.trigger-detail-table th { background: #e2e8f0; color: #4a5568; padding: 5px 8px; font-weight: 500; font-size: 11px; }
|
||||||
|
.trigger-detail-table td { padding: 4px 8px; border-bottom: 1px solid #e2e8f0; }
|
||||||
|
.trigger-detail-table tr:last-child td { border-bottom: none; }
|
||||||
|
.toggle-icon { display: inline-block; width: 16px; font-size: 11px; color: #718096; transition: transform 0.15s; }
|
||||||
|
.toggle-icon.open { transform: rotate(90deg); }
|
||||||
|
.trigger-count { font-size: 11px; color: #718096; font-weight: normal; margin-left: 4px; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Quartz Scheduler Status
|
||||||
|
<% if (autoRefresh) { %><span class="auto-badge">Auto <%= refreshSec %>s</span><% } %>
|
||||||
|
</h1>
|
||||||
|
<p class="info">
|
||||||
|
Instance: <strong><%= System.getProperty("inst.Name", "N/A") %></strong>
|
||||||
|
| Server Time: <strong><%= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) %></strong>
|
||||||
|
</p>
|
||||||
|
<p class="toolbar">
|
||||||
|
Auto Refresh:
|
||||||
|
<% if (!autoRefresh) { %><span class="active">OFF</span><% } else { %><a href="quartzStatus.jsp">OFF</a><% } %>
|
||||||
|
|
|
||||||
|
<% int[] intervals = {5, 10, 30, 60}; %>
|
||||||
|
<% for (int iv : intervals) { %>
|
||||||
|
<% if (autoRefresh && refreshSec == iv) { %><span class="active"><%= iv %>s</span><% } else { %><a href="quartzStatus.jsp?refresh=<%= iv %>"><%= iv %>s</a><% } %>
|
||||||
|
<% } %>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<% if (error != null) { %>
|
||||||
|
<div class="error"><%= error %></div>
|
||||||
|
<% } %>
|
||||||
|
|
||||||
|
<% if (scheduler != null) { %>
|
||||||
|
<h2>Scheduler: <%= scheduler.getSchedulerName() %> (RAM)</h2>
|
||||||
|
<div class="scheduler-meta">
|
||||||
|
<span><strong>Status:</strong> <span class="<%= scheduler.isStarted() ? "state-normal" : "state-error" %>"><%= scheduler.isStarted() ? "STARTED" : "STOPPED" %></span></span>
|
||||||
|
<span><strong>Instance ID:</strong> <%= scheduler.getSchedulerInstanceId() %></span>
|
||||||
|
<span><strong>Job Count:</strong> <%= getJobList(scheduler).size() %></span>
|
||||||
|
</div>
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<th>Job Name</th>
|
||||||
|
<th>Job Class</th>
|
||||||
|
<th>Cron</th>
|
||||||
|
<th>State</th>
|
||||||
|
<th>Concurrent</th>
|
||||||
|
<th>Prev Fire</th>
|
||||||
|
<th>Next Fire</th>
|
||||||
|
<th>Job Data</th>
|
||||||
|
</tr>
|
||||||
|
<% int jobIdx = 0; for (Map<String, Object> job : getJobList(scheduler)) { String rowId = "s_" + jobIdx; List<Map<String, Object>> tList = (List<Map<String, Object>>) job.get("triggerList"); %>
|
||||||
|
<tr class="trigger-toggle" onclick="toggleTriggers('<%= rowId %>')">
|
||||||
|
<td><span class="toggle-icon" id="icon_<%= rowId %>">▶</span><strong><%= job.get("name") %></strong><span class="trigger-count">(<%= job.get("triggerCount") %> triggers)</span></td>
|
||||||
|
<td class="mono"><%= job.get("jobClass") %></td>
|
||||||
|
<td class="mono"><%= job.get("cronExp") %></td>
|
||||||
|
<td class="<%= job.get("stateClass") %>"><%= job.get("state") %></td>
|
||||||
|
<td><span class="badge <%= (Boolean)job.get("disallowConcurrent") ? "badge-yes" : "badge-no" %>">
|
||||||
|
<%= (Boolean)job.get("disallowConcurrent") ? "NO (protected)" : "YES (allowed)" %></span></td>
|
||||||
|
<td class="mono"><%= job.get("prevFire") %><span class="rel"><%= job.get("prevFireRel") %></span></td>
|
||||||
|
<td class="mono"><%= job.get("nextFire") %><span class="rel"><%= job.get("nextFireRel") %></span></td>
|
||||||
|
<td class="mono"><%= job.get("jobData") %></td>
|
||||||
|
</tr>
|
||||||
|
<tr class="trigger-row" id="triggers_<%= rowId %>">
|
||||||
|
<td colspan="8" style="padding: 6px 10px 6px 30px;">
|
||||||
|
<% if (tList.isEmpty()) { %>
|
||||||
|
<em style="color:#a0aec0;">No triggers</em>
|
||||||
|
<% } else { %>
|
||||||
|
<table class="trigger-detail-table">
|
||||||
|
<tr><th>Trigger Name</th><th>Group</th><th>Type</th><th>Expression / Interval</th><th>State</th><th>Priority</th><th>Prev Fire</th><th>Next Fire</th></tr>
|
||||||
|
<% for (Map<String, Object> t : tList) { %>
|
||||||
|
<tr>
|
||||||
|
<td><%= t.get("triggerName") %></td>
|
||||||
|
<td><%= t.get("triggerGroup") %></td>
|
||||||
|
<td><%= t.get("type") %></td>
|
||||||
|
<td class="mono"><%= t.get("cronExp") %></td>
|
||||||
|
<td class="<%= t.get("stateClass") %>"><%= t.get("state") %></td>
|
||||||
|
<td><%= t.get("priority") %></td>
|
||||||
|
<td class="mono"><%= t.get("prevFire") %><span class="rel"><%= t.get("prevFireRel") %></span></td>
|
||||||
|
<td class="mono"><%= t.get("nextFire") %><span class="rel"><%= t.get("nextFireRel") %></span></td>
|
||||||
|
</tr>
|
||||||
|
<% } %>
|
||||||
|
</table>
|
||||||
|
<% } %>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<% jobIdx++; } %>
|
||||||
|
</table>
|
||||||
|
<% } %>
|
||||||
|
|
||||||
|
<% if (clusteredScheduler != null) { %>
|
||||||
|
<h2>Clustered Scheduler: <%= clusteredScheduler.getSchedulerName() %> (DB)</h2>
|
||||||
|
<div class="scheduler-meta">
|
||||||
|
<span><strong>Status:</strong> <span class="<%= clusteredScheduler.isStarted() ? "state-normal" : "state-error" %>"><%= clusteredScheduler.isStarted() ? "STARTED" : "STOPPED" %></span></span>
|
||||||
|
<span><strong>Instance ID:</strong> <%= clusteredScheduler.getSchedulerInstanceId() %></span>
|
||||||
|
<span><strong>Job Count:</strong> <%= getJobList(clusteredScheduler).size() %></span>
|
||||||
|
</div>
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<th>Job Name</th>
|
||||||
|
<th>Job Class</th>
|
||||||
|
<th>Cron</th>
|
||||||
|
<th>State</th>
|
||||||
|
<th>Concurrent</th>
|
||||||
|
<th>Prev Fire</th>
|
||||||
|
<th>Next Fire</th>
|
||||||
|
<th>Job Data</th>
|
||||||
|
</tr>
|
||||||
|
<% int cJobIdx = 0; for (Map<String, Object> job : getJobList(clusteredScheduler)) { String rowId = "c_" + cJobIdx; List<Map<String, Object>> tList = (List<Map<String, Object>>) job.get("triggerList"); %>
|
||||||
|
<tr class="trigger-toggle" onclick="toggleTriggers('<%= rowId %>')">
|
||||||
|
<td><span class="toggle-icon" id="icon_<%= rowId %>">▶</span><strong><%= job.get("name") %></strong><span class="trigger-count">(<%= job.get("triggerCount") %> triggers)</span></td>
|
||||||
|
<td class="mono"><%= job.get("jobClass") %></td>
|
||||||
|
<td class="mono"><%= job.get("cronExp") %></td>
|
||||||
|
<td class="<%= job.get("stateClass") %>"><%= job.get("state") %></td>
|
||||||
|
<td><span class="badge <%= (Boolean)job.get("disallowConcurrent") ? "badge-yes" : "badge-no" %>">
|
||||||
|
<%= (Boolean)job.get("disallowConcurrent") ? "NO (protected)" : "YES (allowed)" %></span></td>
|
||||||
|
<td class="mono"><%= job.get("prevFire") %><span class="rel"><%= job.get("prevFireRel") %></span></td>
|
||||||
|
<td class="mono"><%= job.get("nextFire") %><span class="rel"><%= job.get("nextFireRel") %></span></td>
|
||||||
|
<td class="mono"><%= job.get("jobData") %></td>
|
||||||
|
</tr>
|
||||||
|
<tr class="trigger-row" id="triggers_<%= rowId %>">
|
||||||
|
<td colspan="8" style="padding: 6px 10px 6px 30px;">
|
||||||
|
<% if (tList.isEmpty()) { %>
|
||||||
|
<em style="color:#a0aec0;">No triggers</em>
|
||||||
|
<% } else { %>
|
||||||
|
<table class="trigger-detail-table">
|
||||||
|
<tr><th>Trigger Name</th><th>Group</th><th>Type</th><th>Expression / Interval</th><th>State</th><th>Priority</th><th>Prev Fire</th><th>Next Fire</th></tr>
|
||||||
|
<% for (Map<String, Object> t : tList) { %>
|
||||||
|
<tr>
|
||||||
|
<td><%= t.get("triggerName") %></td>
|
||||||
|
<td><%= t.get("triggerGroup") %></td>
|
||||||
|
<td><%= t.get("type") %></td>
|
||||||
|
<td class="mono"><%= t.get("cronExp") %></td>
|
||||||
|
<td class="<%= t.get("stateClass") %>"><%= t.get("state") %></td>
|
||||||
|
<td><%= t.get("priority") %></td>
|
||||||
|
<td class="mono"><%= t.get("prevFire") %><span class="rel"><%= t.get("prevFireRel") %></span></td>
|
||||||
|
<td class="mono"><%= t.get("nextFire") %><span class="rel"><%= t.get("nextFireRel") %></span></td>
|
||||||
|
</tr>
|
||||||
|
<% } %>
|
||||||
|
</table>
|
||||||
|
<% } %>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<% cJobIdx++; } %>
|
||||||
|
</table>
|
||||||
|
<% } %>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function toggleTriggers(rowId) {
|
||||||
|
var row = document.getElementById('triggers_' + rowId);
|
||||||
|
var icon = document.getElementById('icon_' + rowId);
|
||||||
|
if (row.classList.contains('open')) {
|
||||||
|
row.classList.remove('open');
|
||||||
|
icon.classList.remove('open');
|
||||||
|
} else {
|
||||||
|
row.classList.add('open');
|
||||||
|
icon.classList.add('open');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Binary file not shown.
@@ -259,6 +259,7 @@ public interface MonitoringContext {
|
|||||||
public static final String RMS_AUTO_LOGOUT_TIMEOUT = "rms.auto.logout.timeout";
|
public static final String RMS_AUTO_LOGOUT_TIMEOUT = "rms.auto.logout.timeout";
|
||||||
|
|
||||||
// 웹훅
|
// 웹훅
|
||||||
|
public static final String RMS_WEBHOOK_ENABLED = "rms.webhook.enabled";
|
||||||
public static final String RMS_WEBHOOK_REVERSE_PROXY_URL = "rms.webhook.reverse_proxy.url";
|
public static final String RMS_WEBHOOK_REVERSE_PROXY_URL = "rms.webhook.reverse_proxy.url";
|
||||||
public static final String RMS_WEBHOOK_RETRY_COUNT = "rms.webhook.retry_count";
|
public static final String RMS_WEBHOOK_RETRY_COUNT = "rms.webhook.retry_count";
|
||||||
public static final String RMS_WEBHOOK_RETRY_TIME = "rms.webhook.retry_time";
|
public static final String RMS_WEBHOOK_RETRY_TIME = "rms.webhook.retry_time";
|
||||||
|
|||||||
+1
-1
@@ -20,6 +20,6 @@ public class WebhookReqEventId implements Serializable {
|
|||||||
private String webhookReqId;
|
private String webhookReqId;
|
||||||
|
|
||||||
@Column(name = "EVENT_TYPE", nullable = false, length = 50)
|
@Column(name = "EVENT_TYPE", nullable = false, length = 50)
|
||||||
@Comment("이벤트 유형 (CONTROL_START, ERROR_START 등)")
|
@Comment("이벤트 유형 (CHECK_START, ERROR_START 등)")
|
||||||
private String eventType;
|
private String eventType;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,10 @@ import org.springframework.data.domain.Pageable;
|
|||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import com.eactive.apim.portal.apispec.repository.ApiSpecInfoRepository;
|
||||||
import com.eactive.eai.data.entity.onl.adapter.QAdapter;
|
import com.eactive.eai.data.entity.onl.adapter.QAdapter;
|
||||||
|
import com.eactive.eai.data.entity.onl.apim.apigroup.QApiGroup;
|
||||||
|
import com.eactive.eai.data.entity.onl.apim.apigroup.QApiGroupApi;
|
||||||
import com.eactive.eai.data.entity.onl.authserver.QScopeEntity;
|
import com.eactive.eai.data.entity.onl.authserver.QScopeEntity;
|
||||||
import com.eactive.eai.data.entity.onl.logger.QStatLog;
|
import com.eactive.eai.data.entity.onl.logger.QStatLog;
|
||||||
import com.eactive.eai.data.entity.onl.message.EAIMessageEntity;
|
import com.eactive.eai.data.entity.onl.message.EAIMessageEntity;
|
||||||
@@ -31,6 +34,9 @@ import com.querydsl.core.types.OrderSpecifier;
|
|||||||
import com.querydsl.core.types.Projections;
|
import com.querydsl.core.types.Projections;
|
||||||
import com.querydsl.core.types.dsl.BooleanExpression;
|
import com.querydsl.core.types.dsl.BooleanExpression;
|
||||||
import com.querydsl.core.types.dsl.Expressions;
|
import com.querydsl.core.types.dsl.Expressions;
|
||||||
|
import com.querydsl.core.types.dsl.StringPath;
|
||||||
|
import com.querydsl.jpa.JPAExpressions;
|
||||||
|
import com.querydsl.jpa.JPQLQuery;
|
||||||
import com.querydsl.jpa.impl.JPAQuery;
|
import com.querydsl.jpa.impl.JPAQuery;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@@ -38,8 +44,14 @@ import com.querydsl.jpa.impl.JPAQuery;
|
|||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class EAIMessageService extends AbstractDataService<EAIMessageEntity, String, EAIMessageRepository> {
|
public class EAIMessageService extends AbstractDataService<EAIMessageEntity, String, EAIMessageRepository> {
|
||||||
|
|
||||||
|
/** Oracle IN 절 표현식 개수 상한. 넘기면 ORA-01795 라 나눠 OR 로 잇는다 */
|
||||||
|
private static final int ORACLE_IN_LIMIT = 1000;
|
||||||
|
|
||||||
private final UserBusinessService userBusinessService;
|
private final UserBusinessService userBusinessService;
|
||||||
|
|
||||||
|
/** EMSAPP(PTL_API_SPEC_INFO) 조회용. 다른 스키마라 EAI 메시지 쿼리에 조인할 수 없다 */
|
||||||
|
private final ApiSpecInfoRepository apiSpecInfoRepository;
|
||||||
|
|
||||||
public Page<Tuple> selectList(EAIMessageUISearch eaiMessageUISearch, Pageable pageable, String sortname, String sortorder) {
|
public Page<Tuple> selectList(EAIMessageUISearch eaiMessageUISearch, Pageable pageable, String sortname, String sortorder) {
|
||||||
|
|
||||||
QEAIMessageEntity qeaiMessageEntity = QEAIMessageEntity.eAIMessageEntity;
|
QEAIMessageEntity qeaiMessageEntity = QEAIMessageEntity.eAIMessageEntity;
|
||||||
@@ -115,6 +127,7 @@ public class EAIMessageService extends AbstractDataService<EAIMessageEntity, Str
|
|||||||
return getJPAQueryFactory()
|
return getJPAQueryFactory()
|
||||||
.select(qeaiMessageEntity
|
.select(qeaiMessageEntity
|
||||||
, qServiceMessageEntity.psvintfacdsticname
|
, qServiceMessageEntity.psvintfacdsticname
|
||||||
|
, qServiceMessageEntity.psvsysadptrbzwkgroupname
|
||||||
, qRouting.nonmotivrouturiname
|
, qRouting.nonmotivrouturiname
|
||||||
, qStdInfo.apifullpath
|
, qStdInfo.apifullpath
|
||||||
, qStdInfo.bzwksvckeyname
|
, qStdInfo.bzwksvckeyname
|
||||||
@@ -136,7 +149,6 @@ public class EAIMessageService extends AbstractDataService<EAIMessageEntity, Str
|
|||||||
|
|
||||||
QEAIMessageEntity qeaiMessageEntity = QEAIMessageEntity.eAIMessageEntity;
|
QEAIMessageEntity qeaiMessageEntity = QEAIMessageEntity.eAIMessageEntity;
|
||||||
QServiceMessageEntity qServiceMessageEntity = QServiceMessageEntity.serviceMessageEntity;
|
QServiceMessageEntity qServiceMessageEntity = QServiceMessageEntity.serviceMessageEntity;
|
||||||
QRouting qRouting = QRouting.routing;
|
|
||||||
QStandardMessageInfo qStdInfo = QStandardMessageInfo.standardMessageInfo;
|
QStandardMessageInfo qStdInfo = QStandardMessageInfo.standardMessageInfo;
|
||||||
|
|
||||||
BooleanBuilder predicate = new BooleanBuilder();
|
BooleanBuilder predicate = new BooleanBuilder();
|
||||||
@@ -154,11 +166,10 @@ public class EAIMessageService extends AbstractDataService<EAIMessageEntity, Str
|
|||||||
if (StringUtils.isNotBlank(eaiMessageUISearch.getSearchEaiSvcDesc())) {
|
if (StringUtils.isNotBlank(eaiMessageUISearch.getSearchEaiSvcDesc())) {
|
||||||
predicate.and(qeaiMessageEntity.eaisvcdesc.containsIgnoreCase(eaiMessageUISearch.getSearchEaiSvcDesc()));
|
predicate.and(qeaiMessageEntity.eaisvcdesc.containsIgnoreCase(eaiMessageUISearch.getSearchEaiSvcDesc()));
|
||||||
}
|
}
|
||||||
if (StringUtils.isNotBlank(eaiMessageUISearch.getSearchSvcMotivUsedStcd())) {
|
if (StringUtils.isNotBlank(eaiMessageUISearch.getSearchGstatSysAdptrBzwkGroupName())) {
|
||||||
predicate.and(qeaiMessageEntity.svcmotivusedstcd.eq(eaiMessageUISearch.getSearchSvcMotivUsedStcd()));
|
predicate
|
||||||
}
|
.and(qeaiMessageEntity.gstatsysadptrbzwkgroupname
|
||||||
if (StringUtils.isNotBlank(eaiMessageUISearch.getSearchFlowControl())) {
|
.containsIgnoreCase(eaiMessageUISearch.getSearchGstatSysAdptrBzwkGroupName()));
|
||||||
predicate.and(qeaiMessageEntity.flowctrlroutname.eq(eaiMessageUISearch.getSearchFlowControl()));
|
|
||||||
}
|
}
|
||||||
if (StringUtils.isNotBlank(eaiMessageUISearch.getSearchTranType())) {
|
if (StringUtils.isNotBlank(eaiMessageUISearch.getSearchTranType())) {
|
||||||
predicate.and(qeaiMessageEntity.trantype.eq(eaiMessageUISearch.getSearchTranType()));
|
predicate.and(qeaiMessageEntity.trantype.eq(eaiMessageUISearch.getSearchTranType()));
|
||||||
@@ -178,18 +189,11 @@ public class EAIMessageService extends AbstractDataService<EAIMessageEntity, Str
|
|||||||
predicate.and(qeaiMessageEntity.refkey.containsIgnoreCase(eaiMessageUISearch.getSearchRefKey()));
|
predicate.and(qeaiMessageEntity.refkey.containsIgnoreCase(eaiMessageUISearch.getSearchRefKey()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (StringUtils.isNotBlank(eaiMessageUISearch.getSearchQueueName())) {
|
if (StringUtils.isNotBlank(eaiMessageUISearch.getSearchPsvSysAdptrBzwkGroupName())) {
|
||||||
predicate
|
|
||||||
.and(qeaiMessageEntity.flowctrlroutname.eq(qRouting.routname))
|
|
||||||
.and(qRouting.nonmotivrouturiname.containsIgnoreCase(eaiMessageUISearch.getSearchQueueName()));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (StringUtils.isNotBlank(eaiMessageUISearch.getSearchPsvintfacdsticName())) {
|
|
||||||
predicate
|
predicate
|
||||||
.and(qServiceMessageEntity.id.svcprcssno.eq(1))
|
.and(qServiceMessageEntity.id.svcprcssno.eq(1))
|
||||||
.and(qServiceMessageEntity.psvintfacdsticname
|
.and(qServiceMessageEntity.psvsysadptrbzwkgroupname
|
||||||
.containsIgnoreCase(eaiMessageUISearch.getSearchPsvintfacdsticName()));
|
.containsIgnoreCase(eaiMessageUISearch.getSearchPsvSysAdptrBzwkGroupName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (StringUtils.isNotBlank(eaiMessageUISearch.getSearchApiFullPath())) {
|
if (StringUtils.isNotBlank(eaiMessageUISearch.getSearchApiFullPath())) {
|
||||||
@@ -197,9 +201,51 @@ public class EAIMessageService extends AbstractDataService<EAIMessageEntity, Str
|
|||||||
.and(qStdInfo.apifullpath.contains(eaiMessageUISearch.getSearchApiFullPath()));
|
.and(qStdInfo.apifullpath.contains(eaiMessageUISearch.getSearchApiFullPath()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ("Y".equals(eaiMessageUISearch.getSearchApiSpecYn())) {
|
||||||
|
predicate.and(apiSpecRegisteredExpression(qeaiMessageEntity.eaisvcname));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ("Y".equals(eaiMessageUISearch.getSearchPortalDisplayYn())) {
|
||||||
|
predicate.and(qeaiMessageEntity.eaisvcname.in(displayedGroupApiIdSubQuery()));
|
||||||
|
}
|
||||||
|
|
||||||
return predicate;
|
return predicate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OpenAPI Spec 등록 여부 조건.
|
||||||
|
*
|
||||||
|
* <p>PTL_API_SPEC_INFO 는 EMSAPP 스키마라 TSEAIHE01 쿼리에 조인하면 ORA-00942 다. 스펙이 있는
|
||||||
|
* API ID 를 EMS 커넥션에서 따로 읽어 IN 절로 넘긴다.</p>
|
||||||
|
*/
|
||||||
|
private BooleanExpression apiSpecRegisteredExpression(StringPath eaiSvcNamePath) {
|
||||||
|
List<String> specApiIds = apiSpecInfoRepository.findAllApiIds();
|
||||||
|
if (specApiIds.isEmpty()) {
|
||||||
|
// in(빈 리스트) 는 JPQL 이 깨지므로 항상 거짓인 조건으로 대체한다
|
||||||
|
return Expressions.ONE.eq(Expressions.TWO);
|
||||||
|
}
|
||||||
|
|
||||||
|
BooleanExpression expression = null;
|
||||||
|
for (int from = 0; from < specApiIds.size(); from += ORACLE_IN_LIMIT) {
|
||||||
|
int to = Math.min(from + ORACLE_IN_LIMIT, specApiIds.size());
|
||||||
|
BooleanExpression chunk = eaiSvcNamePath.in(specApiIds.subList(from, to));
|
||||||
|
expression = (expression == null) ? chunk : expression.or(chunk);
|
||||||
|
}
|
||||||
|
return expression;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 노출 중인(display_yn='1') API 그룹에 편성된 API ID. API_GROUP 은 EAI 메시지와 같은 스키마다 */
|
||||||
|
private JPQLQuery<String> displayedGroupApiIdSubQuery() {
|
||||||
|
QApiGroupApi qApiGroupApi = QApiGroupApi.apiGroupApi;
|
||||||
|
QApiGroup qApiGroup = QApiGroup.apiGroup;
|
||||||
|
|
||||||
|
return JPAExpressions
|
||||||
|
.select(qApiGroupApi.id.apiId)
|
||||||
|
.from(qApiGroupApi)
|
||||||
|
.join(qApiGroupApi.apiGroup, qApiGroup)
|
||||||
|
.where(qApiGroup.displayYn.eq("1"));
|
||||||
|
}
|
||||||
|
|
||||||
public Page<RoutingEaiMsgDto> findAll(Pageable pageable, RoutingEaiMsgSearch routingEaiMsgSearch) {
|
public Page<RoutingEaiMsgDto> findAll(Pageable pageable, RoutingEaiMsgSearch routingEaiMsgSearch) {
|
||||||
|
|
||||||
List<RoutingEaiMsgDto> result = routingEaiMsgDtoList(pageable, routingEaiMsgSearch);
|
List<RoutingEaiMsgDto> result = routingEaiMsgDtoList(pageable, routingEaiMsgSearch);
|
||||||
|
|||||||
@@ -8,13 +8,11 @@ public class EAIMessageUISearch {
|
|||||||
private String searchEaiSvcName;
|
private String searchEaiSvcName;
|
||||||
private String searchEaiBzwkDstcd;
|
private String searchEaiBzwkDstcd;
|
||||||
private String searchEaiSvcDesc;
|
private String searchEaiSvcDesc;
|
||||||
private String searchSvcMotivUsedStcd;
|
private String searchGstatSysAdptrBzwkGroupName;
|
||||||
private String searchFlowControl;
|
|
||||||
private String searchTranType;
|
private String searchTranType;
|
||||||
private String searchQueueName;
|
|
||||||
|
|
||||||
private String rmsMenuAuth;
|
private String rmsMenuAuth;
|
||||||
private String searchPsvintfacdsticName;
|
private String searchPsvSysAdptrBzwkGroupName;
|
||||||
private String searchExtBizCd;
|
private String searchExtBizCd;
|
||||||
|
|
||||||
private String tranChangeSim;
|
private String tranChangeSim;
|
||||||
@@ -22,4 +20,10 @@ public class EAIMessageUISearch {
|
|||||||
|
|
||||||
private String searchApiFullPath;
|
private String searchApiFullPath;
|
||||||
|
|
||||||
|
/** "Y" 면 PTL_API_SPEC_INFO 에 OpenAPI Spec 이 등록된 API 만 조회 */
|
||||||
|
private String searchApiSpecYn;
|
||||||
|
|
||||||
|
/** "Y" 면 노출 중인(display_yn='1') API 그룹에 편성된 API 만 조회 */
|
||||||
|
private String searchPortalDisplayYn;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -102,9 +102,15 @@ public class EAILogRepositoryImpl implements EAILogRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (StringUtils.isNotBlank(eaiLogSearch.getSearchGuid())) {
|
if (StringUtils.isNotBlank(eaiLogSearch.getSearchGuid())) {
|
||||||
query
|
query.where(qeaiLog.pguid.eq(eaiLogSearch.getSearchGuid()));
|
||||||
.where(qeaiLog.pguid.eq(eaiLogSearch.getSearchGuid()))
|
|
||||||
.where(qeaiLog.id.logprcssserno.eq(eaiLogSearch.getSearchLogPrcssSerno()));
|
// 처리단계(logprcssserno)를 명시적으로 선택한 경우에만 추가로 좁힌다.
|
||||||
|
// 하나의 GUID는 처리단계(100/200/300/400)별로 여러 로그 행에 걸쳐 존재하므로,
|
||||||
|
// 선택하지 않았으면 해당 GUID의 모든 단계를 조회한다.
|
||||||
|
if (StringUtils.isNotBlank(eaiLogSearch.getSearchLogPrcssSerno())) {
|
||||||
|
query.where(qeaiLog.id.logprcssserno.eq(eaiLogSearch.getSearchLogPrcssSerno()));
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import org.springframework.data.domain.Pageable;
|
|||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import com.eactive.eai.common.util.UUIDGenerator;
|
||||||
import com.eactive.eai.data.RollingTable;
|
import com.eactive.eai.data.RollingTable;
|
||||||
import com.eactive.eai.data.entity.onl.logger.EAILog;
|
import com.eactive.eai.data.entity.onl.logger.EAILog;
|
||||||
import com.eactive.eai.data.entity.onl.logger.EAILogId;
|
import com.eactive.eai.data.entity.onl.logger.EAILogId;
|
||||||
@@ -38,19 +39,36 @@ public class EAILogServiceImpl implements EAILogService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Page<EAILogDto> findAll(Pageable pageable, EAILogSearch eaiLogSearch) {
|
public Page<EAILogDto> findAll(Pageable pageable, EAILogSearch eaiLogSearch) {
|
||||||
long time = CommonUtil.getCalendar(eaiLogSearch.getSearchStartTime()).getTimeInMillis();
|
long time = CommonUtil.getCalendar(resolveTableDate(eaiLogSearch)).getTimeInMillis();
|
||||||
EAILog eaiLog = (EAILog) applicationContext.getBean(RollingTable.class, EAILog.class, time);
|
EAILog eaiLog = (EAILog) applicationContext.getBean(RollingTable.class, EAILog.class, time);
|
||||||
Page<EAILogDto> eaiLogDtos = eaiLogRepository.findAll(eaiLog.getClass(), pageable, eaiLogSearch);
|
Page<EAILogDto> eaiLogDtos = eaiLogRepository.findAll(eaiLog.getClass(), pageable, eaiLogSearch);
|
||||||
return eaiLogDtos;
|
return eaiLogDtos;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, Long> getTransactionCounts(EAILogSearch eaiLogSearch) {
|
public Map<String, Long> getTransactionCounts(EAILogSearch eaiLogSearch) {
|
||||||
long time = CommonUtil.getCalendar(eaiLogSearch.getSearchStartTime()).getTimeInMillis();
|
long time = CommonUtil.getCalendar(resolveTableDate(eaiLogSearch)).getTimeInMillis();
|
||||||
EAILog eaiLog = (EAILog) applicationContext.getBean(RollingTable.class, EAILog.class, time);
|
EAILog eaiLog = (EAILog) applicationContext.getBean(RollingTable.class, EAILog.class, time);
|
||||||
Map<String, Long> detailedCounts = eaiLogRepository.countDetailedTransactions(eaiLog.getClass(), eaiLogSearch);
|
Map<String, Long> detailedCounts = eaiLogRepository.countDetailedTransactions(eaiLog.getClass(), eaiLogSearch);
|
||||||
return detailedCounts;
|
return detailedCounts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GUID로 조회하는 경우, 대상 롤링 테이블을 검색시간이 아닌 GUID 자체에 포함된 시각으로 특정한다.
|
||||||
|
// GUID 포맷/오프셋은 UUIDGenerator.GUID_DATE_POSITION 기준.
|
||||||
|
private String resolveTableDate(EAILogSearch eaiLogSearch) {
|
||||||
|
String guid = eaiLogSearch.getSearchGuid();
|
||||||
|
|
||||||
|
if (StringUtils.isNotBlank(guid)) {
|
||||||
|
int start = UUIDGenerator.GUID_DATE_POSITION;
|
||||||
|
int end = start + 14; // yyyyMMddHHmmss
|
||||||
|
|
||||||
|
if (guid.length() >= end) {
|
||||||
|
return guid.substring(start, end);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return eaiLogSearch.getSearchStartTime();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EAILogDto getById(EAILogId eaiLogId) {
|
public EAILogDto getById(EAILogId eaiLogId) {
|
||||||
long time = CommonUtil.getCalendar(eaiLogId.getMsgdpstyms()).getTimeInMillis();
|
long time = CommonUtil.getCalendar(eaiLogId.getMsgdpstyms()).getTimeInMillis();
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import org.springframework.dao.DataIntegrityViolationException;
|
|||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import com.eactive.apim.portal.apispec.repository.ApiSpecInfoRepository;
|
||||||
import com.eactive.apim.portal.common.entity.Auditable;
|
import com.eactive.apim.portal.common.entity.Auditable;
|
||||||
import com.eactive.apim.portal.djb.apistatus.incident.entity.DjbApistatusIncident;
|
import com.eactive.apim.portal.djb.apistatus.incident.entity.DjbApistatusIncident;
|
||||||
import com.eactive.apim.portal.djb.apistatus.incident.entity.DjbApistatusIncidentApi;
|
import com.eactive.apim.portal.djb.apistatus.incident.entity.DjbApistatusIncidentApi;
|
||||||
@@ -58,8 +59,8 @@ public class ApiStatusDetectionService {
|
|||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(ApiStatusDetectionService.class);
|
private static final Logger log = LoggerFactory.getLogger(ApiStatusDetectionService.class);
|
||||||
|
|
||||||
public static final String EVENT_CONTROL_START = "CONTROL_START";
|
public static final String EVENT_CHECK_START = "CHECK_START";
|
||||||
public static final String EVENT_CONTROL_END = "CONTROL_END";
|
public static final String EVENT_CHECK_END = "CHECK_END";
|
||||||
public static final String EVENT_ERROR_START = "ERROR_START";
|
public static final String EVENT_ERROR_START = "ERROR_START";
|
||||||
public static final String EVENT_ERROR_END = "ERROR_END";
|
public static final String EVENT_ERROR_END = "ERROR_END";
|
||||||
public static final String EVENT_DELAY_START = "DELAY_START";
|
public static final String EVENT_DELAY_START = "DELAY_START";
|
||||||
@@ -110,6 +111,10 @@ public class ApiStatusDetectionService {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private ApiStatusRepository apiStatusRepository;
|
private ApiStatusRepository apiStatusRepository;
|
||||||
|
|
||||||
|
/** EMSAPP(PTL_API_SPEC_INFO) 조회용. AGWAPP 커넥션으로 도는 apiStatusRepository 로는 못 읽는다 */
|
||||||
|
@Autowired
|
||||||
|
private ApiSpecInfoRepository apiSpecInfoRepository;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private PortalPropertyService portalPropertyService;
|
private PortalPropertyService portalPropertyService;
|
||||||
|
|
||||||
@@ -119,8 +124,8 @@ public class ApiStatusDetectionService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 이벤트 감지
|
* 이벤트 감지
|
||||||
* @param event "CONTROL_START" : 점검시작
|
* @param event "CHECK_START" : 점검시작
|
||||||
"CONTROL_END" : 점검종료
|
"CHECK_END" : 점검종료
|
||||||
"ERROR_START" : 장애시작
|
"ERROR_START" : 장애시작
|
||||||
"ERROR_END" : 장애종료
|
"ERROR_END" : 장애종료
|
||||||
"DELAY_START" : 지연시작
|
"DELAY_START" : 지연시작
|
||||||
@@ -154,8 +159,8 @@ public class ApiStatusDetectionService {
|
|||||||
case EVENT_DELAY_END:
|
case EVENT_DELAY_END:
|
||||||
markRecovered(event, targets);
|
markRecovered(event, targets);
|
||||||
break;
|
break;
|
||||||
case EVENT_CONTROL_START:
|
case EVENT_CHECK_START:
|
||||||
case EVENT_CONTROL_END:
|
case EVENT_CHECK_END:
|
||||||
// 점검은 관리자 등록 공지가 원천 - 재기록하지 않음
|
// 점검은 관리자 등록 공지가 원천 - 재기록하지 않음
|
||||||
log.debug("점검 이벤트는 장애 데이터로 기록하지 않음: {} {}", event, targets);
|
log.debug("점검 이벤트는 장애 데이터로 기록하지 않음: {} {}", event, targets);
|
||||||
break;
|
break;
|
||||||
@@ -534,14 +539,23 @@ public class ApiStatusDetectionService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 게시 인터페이스 판정. 조회에 실패하면 전부 비게시로 보아 ID·명칭 노출을 막는다. */
|
/**
|
||||||
|
* 게시 인터페이스 판정. 조회에 실패하면 전부 비게시로 보아 ID·명칭 노출을 막는다.
|
||||||
|
*
|
||||||
|
* <p>판정 조건 두 개가 서로 다른 스키마에 있어 조회를 나눈다 - API 그룹 편성은 AGWAPP,
|
||||||
|
* 스펙 존재는 EMSAPP(PTL_API_SPEC_INFO). 한 쿼리로 조인하면 tenant=APIGW 커넥션이
|
||||||
|
* EMSAPP 를 못 봐서 ORA-00942 가 난다.</p>
|
||||||
|
*/
|
||||||
private ApiSplit splitPublished(List<String> apiIds) {
|
private ApiSplit splitPublished(List<String> apiIds) {
|
||||||
if (apiIds == null || apiIds.isEmpty()) {
|
if (apiIds == null || apiIds.isEmpty()) {
|
||||||
return new ApiSplit(Collections.emptyList(), 0);
|
return new ApiSplit(Collections.emptyList(), 0);
|
||||||
}
|
}
|
||||||
Set<String> publishedIds;
|
Set<String> publishedIds;
|
||||||
try {
|
try {
|
||||||
publishedIds = new HashSet<>(apiStatusRepository.findPublishedApiIds(apiIds));
|
List<String> groupedIds = apiStatusRepository.findDisplayedGroupApiIds(apiIds);
|
||||||
|
publishedIds = groupedIds.isEmpty()
|
||||||
|
? Collections.emptySet()
|
||||||
|
: new HashSet<>(apiSpecInfoRepository.findApiIdsIn(groupedIds));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
// 실패 시 노출하는 쪽으로 기울면 내부 인터페이스가 고객 화면에 새어 나간다
|
// 실패 시 노출하는 쪽으로 기울면 내부 인터페이스가 고객 화면에 새어 나간다
|
||||||
log.warn("게시 API 판정 실패 - 전부 GW 인터페이스로 묶어 표기", e);
|
log.warn("게시 API 판정 실패 - 전부 GW 인터페이스로 묶어 표기", e);
|
||||||
|
|||||||
@@ -17,8 +17,8 @@ public interface ApiStatusRepository extends BaseRepository<ApiStatus, String> {
|
|||||||
/**
|
/**
|
||||||
* API 상태 판단. 정상(N), 점검(C), 지연(D), 장애(E)
|
* API 상태 판단. 정상(N), 점검(C), 지연(D), 장애(E)
|
||||||
*
|
*
|
||||||
* 1. 정상/지연/장애 -> 점검중 : CONTROL_START
|
* 1. 정상/지연/장애 -> 점검중 : CHECK_START
|
||||||
* 2. 점검 -> 점검X : CONTROL_END
|
* 2. 점검 -> 점검X : CHECK_END
|
||||||
* 3. 정상/지연 -> 장애 : ERROR_START
|
* 3. 정상/지연 -> 장애 : ERROR_START
|
||||||
* 4. 장애 -> 장애X : ERROR_END
|
* 4. 장애 -> 장애X : ERROR_END
|
||||||
* 5. 정상 -> 지연 : DELAY_START
|
* 5. 정상 -> 지연 : DELAY_START
|
||||||
@@ -34,8 +34,8 @@ public interface ApiStatusRepository extends BaseRepository<ApiStatus, String> {
|
|||||||
+ " FROM ("
|
+ " FROM ("
|
||||||
+ " SELECT EAISVCNAME"
|
+ " SELECT EAISVCNAME"
|
||||||
+ " , STATUS_CODE AS PREV_STATUS_CODE "
|
+ " , STATUS_CODE AS PREV_STATUS_CODE "
|
||||||
+ " , CASE WHEN STATUS_CODE != 'C' AND CTRL_YN = 'Y' THEN 'CONTROL_START'"
|
+ " , CASE WHEN STATUS_CODE != 'C' AND CTRL_YN = 'Y' THEN 'CHECK_START'"
|
||||||
+ " WHEN STATUS_CODE = 'C' AND CTRL_YN = 'N' THEN 'CONTROL_END'"
|
+ " WHEN STATUS_CODE = 'C' AND CTRL_YN = 'N' THEN 'CHECK_END'"
|
||||||
+ " WHEN STATUS_CODE IN ('N','D') AND ERR_YN = 'Y' THEN 'ERROR_START'"
|
+ " WHEN STATUS_CODE IN ('N','D') AND ERR_YN = 'Y' THEN 'ERROR_START'"
|
||||||
+ " WHEN STATUS_CODE = 'E' AND ERR_YN = 'N' THEN 'ERROR_END'"
|
+ " WHEN STATUS_CODE = 'E' AND ERR_YN = 'N' THEN 'ERROR_END'"
|
||||||
+ " WHEN STATUS_CODE = 'N' AND DELAY_YN = 'Y' THEN 'DELAY_START'"
|
+ " WHEN STATUS_CODE = 'N' AND DELAY_YN = 'Y' THEN 'DELAY_START'"
|
||||||
@@ -45,7 +45,7 @@ public interface ApiStatusRepository extends BaseRepository<ApiStatus, String> {
|
|||||||
+ " SELECT A.EAISVCNAME"
|
+ " SELECT A.EAISVCNAME"
|
||||||
+ " , NVL(B.STATUS_CODE, 'N') AS STATUS_CODE"
|
+ " , NVL(B.STATUS_CODE, 'N') AS STATUS_CODE"
|
||||||
// 점검(KIND='MAINTENANCE')만 CTRL_YN 대상이다. KIND 를 안 걸면 관리자가 시작~종료 시각을
|
// 점검(KIND='MAINTENANCE')만 CTRL_YN 대상이다. KIND 를 안 걸면 관리자가 시작~종료 시각을
|
||||||
// 넣어 등록한 장애 공지까지 '점검중'으로 오판해 CONTROL_START 가 발생한다.
|
// 넣어 등록한 장애 공지까지 '점검중'으로 오판해 CHECK_START 가 발생한다.
|
||||||
+ " , NVL(( SELECT MAX('Y') FROM EMSAPP.DJB_APISTATUS_INCIDENT_API X"
|
+ " , NVL(( SELECT MAX('Y') FROM EMSAPP.DJB_APISTATUS_INCIDENT_API X"
|
||||||
+ " WHERE EXISTS (SELECT 1 FROM EMSAPP.DJB_APISTATUS_INCIDENT Y WHERE X.INCIDENT_ID = Y.INCIDENT_ID "
|
+ " WHERE EXISTS (SELECT 1 FROM EMSAPP.DJB_APISTATUS_INCIDENT Y WHERE X.INCIDENT_ID = Y.INCIDENT_ID "
|
||||||
+ " AND Y.KIND = 'MAINTENANCE'"
|
+ " AND Y.KIND = 'MAINTENANCE'"
|
||||||
@@ -147,22 +147,25 @@ public interface ApiStatusRepository extends BaseRepository<ApiStatus, String> {
|
|||||||
List<ApiNameRow> findApiNames(@Param("apiIds") Collection<String> apiIds);
|
List<ApiNameRow> findApiNames(@Param("apiIds") Collection<String> apiIds);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 개발자포탈에 게시되는 인터페이스(= API) 만 추린다.
|
* 노출 중인 API 그룹에 편성된 인터페이스 ID.
|
||||||
*
|
*
|
||||||
* <p>GW 인터페이스는 전부 탐지 대상이지만 개발자포탈에 노출되는 것은 그 일부다.
|
* <p>GW 인터페이스는 전부 탐지 대상이지만 개발자포탈에 노출되는 것은 그 일부다.
|
||||||
* 자동 초안(제목·공지 본문·타임라인)에 게시되지 않은 인터페이스 ID 가 그대로 박히면
|
* 자동 초안(제목·공지 본문·타임라인)에 게시되지 않은 인터페이스 ID 가 그대로 박히면
|
||||||
* 고객 화면에 내부 인터페이스가 드러나므로, 여기서 걸러 나머지는 건수로만 표기한다.</p>
|
* 고객 화면에 내부 인터페이스가 드러나므로, 여기서 걸러 나머지는 건수로만 표기한다.</p>
|
||||||
*
|
*
|
||||||
* <p>판정 기준은 포털 "오픈 API" 목록과 같은 두 조건이다 - 노출 중인 API 그룹에 편성돼 있고
|
* <p>게시 판정은 포털 "오픈 API" 목록과 같은 두 조건이다 - 노출 중인 API 그룹에 편성돼 있고
|
||||||
* PTL_API_SPEC_INFO 에 스펙이 있을 것. 역할·소속에 따른 사용자별 공개 범위는 admin 에
|
* PTL_API_SPEC_INFO 에 스펙이 있을 것. 이 쿼리는 앞 조건(AGWAPP)만 본다. 뒤 조건은
|
||||||
* 사용자 컨텍스트가 없어 적용하지 않는다(= 포털 화면이 한 번 더 좁힌다).</p>
|
* EMSAPP 스키마라 {@code ApiSpecInfoRepository.findApiIdsIn} 으로 따로 조회해 교집합을 잡는다
|
||||||
|
* - 이 리포지토리는 tenant=APIGW(AGWAPP) 커넥션으로 도는 탓에 한 쿼리로 조인하면 ORA-00942 다.</p>
|
||||||
|
*
|
||||||
|
* <p>역할·소속에 따른 사용자별 공개 범위는 admin 에 사용자 컨텍스트가 없어 적용하지 않는다
|
||||||
|
* (= 포털 화면이 한 번 더 좁힌다).</p>
|
||||||
*/
|
*/
|
||||||
@Query(nativeQuery = true, value =
|
@Query(nativeQuery = true, value =
|
||||||
" SELECT DISTINCT GA.API_ID"
|
" SELECT DISTINCT GA.API_ID"
|
||||||
+ " FROM API_GROUP_API GA"
|
+ " FROM API_GROUP_API GA"
|
||||||
+ " JOIN API_GROUP G ON G.ID = GA.API_GROUP_ID"
|
+ " JOIN API_GROUP G ON G.ID = GA.API_GROUP_ID"
|
||||||
+ " WHERE GA.API_ID IN (:apiIds)"
|
+ " WHERE GA.API_ID IN (:apiIds)"
|
||||||
+ " AND G.DISPLAY_YN = '1'"
|
+ " AND G.DISPLAY_YN = '1'")
|
||||||
+ " AND EXISTS (SELECT 1 FROM EMSAPP.PTL_API_SPEC_INFO S WHERE S.API_ID = GA.API_ID)")
|
List<String> findDisplayedGroupApiIds(@Param("apiIds") Collection<String> apiIds);
|
||||||
List<String> findPublishedApiIds(@Param("apiIds") Collection<String> apiIds);
|
|
||||||
}
|
}
|
||||||
@@ -14,6 +14,7 @@ import org.springframework.stereotype.Service;
|
|||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
import com.eactive.apim.portal.template.entity.MessageCode;
|
import com.eactive.apim.portal.template.entity.MessageCode;
|
||||||
|
import com.eactive.eai.rms.common.context.MonitoringContext;
|
||||||
import com.eactive.eai.rms.data.entity.man.role.Role;
|
import com.eactive.eai.rms.data.entity.man.role.Role;
|
||||||
import com.eactive.eai.rms.data.entity.onl.djb.apistatus.ApiErrorRateRow;
|
import com.eactive.eai.rms.data.entity.onl.djb.apistatus.ApiErrorRateRow;
|
||||||
import com.eactive.eai.rms.data.entity.onl.djb.apistatus.ApiStatus;
|
import com.eactive.eai.rms.data.entity.onl.djb.apistatus.ApiStatus;
|
||||||
@@ -36,6 +37,9 @@ public class ApiStatusService {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private ApiStatusDetectionService apiStatusDectionService;
|
private ApiStatusDetectionService apiStatusDectionService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private MonitoringContext monitoringContext;
|
||||||
|
|
||||||
|
|
||||||
public void updateApiStatus(HashMap<String, String> param) {
|
public void updateApiStatus(HashMap<String, String> param) {
|
||||||
|
|
||||||
@@ -90,7 +94,9 @@ public class ApiStatusService {
|
|||||||
ums.send("api-monitor", MessageCode.API_STATUS_CHANGED, params);
|
ums.send("api-monitor", MessageCode.API_STATUS_CHANGED, params);
|
||||||
|
|
||||||
//제휴사 웹훅 발송
|
//제휴사 웹훅 발송
|
||||||
ums.sendWebhook(event, apiIds);
|
if (monitoringContext.getBooleanProperty(MonitoringContext.RMS_WEBHOOK_ENABLED, true)) {
|
||||||
|
ums.sendWebhook(event, apiIds);
|
||||||
|
}
|
||||||
|
|
||||||
//개발자포탈 API상태모니터링 화면을 위한 처리
|
//개발자포탈 API상태모니터링 화면을 위한 처리
|
||||||
apiStatusDectionService.detect(event, apiIds);
|
apiStatusDectionService.detect(event, apiIds);
|
||||||
@@ -179,8 +185,8 @@ public class ApiStatusService {
|
|||||||
|
|
||||||
private String resolveStatusCode(String event) {
|
private String resolveStatusCode(String event) {
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case "CONTROL_START": return "C"; //점검
|
case "CHECK_START": return "C"; //점검
|
||||||
case "CONTROL_END": return "N"; //정상
|
case "CHECK_END": return "N"; //정상
|
||||||
case "ERROR_START": return "E"; //장애
|
case "ERROR_START": return "E"; //장애
|
||||||
case "ERROR_END": return "N"; //정상
|
case "ERROR_END": return "N"; //정상
|
||||||
case "DELAY_START": return "D"; //지연
|
case "DELAY_START": return "D"; //지연
|
||||||
@@ -195,10 +201,10 @@ public class ApiStatusService {
|
|||||||
private HashMap<String, Object> getSwingChatMessage(String event, List<String> apiIds) {
|
private HashMap<String, Object> getSwingChatMessage(String event, List<String> apiIds) {
|
||||||
String message = "";
|
String message = "";
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case "CONTROL_START":
|
case "CHECK_START":
|
||||||
message = "API 서비스 점검이 시작되었습니다"; //점검
|
message = "API 서비스 점검이 시작되었습니다"; //점검
|
||||||
break;
|
break;
|
||||||
case "CONTROL_END":
|
case "CHECK_END":
|
||||||
message = "API 서비스 점검이 완료되었습니다"; //정상
|
message = "API 서비스 점검이 완료되었습니다"; //정상
|
||||||
break;
|
break;
|
||||||
case "ERROR_START":
|
case "ERROR_START":
|
||||||
|
|||||||
@@ -166,6 +166,7 @@ public class UmsService {
|
|||||||
if ("MESSENGER".equals(messageRequest.getMessageType()) ) {
|
if ("MESSENGER".equals(messageRequest.getMessageType()) ) {
|
||||||
|
|
||||||
stdHeadVO.setChnl_tycd("FEP"); // 채널유형코드
|
stdHeadVO.setChnl_tycd("FEP"); // 채널유형코드
|
||||||
|
stdHeadVO.setHmab_dvcd("2"); // 내외구분코드 1:내부 2:외부(타발)
|
||||||
|
|
||||||
// 스윙챗 알림 공용
|
// 스윙챗 알림 공용
|
||||||
SwingCommonVO swiComVO = new SwingCommonVO();
|
SwingCommonVO swiComVO = new SwingCommonVO();
|
||||||
@@ -253,12 +254,9 @@ public class UmsService {
|
|||||||
dataVO.setUms_evnt_id(propertyService.getPropertyValue("Monitoring", "djb.ums.email.ums_evnt_id", "")); // UMS이벤트ID(필수)
|
dataVO.setUms_evnt_id(propertyService.getPropertyValue("Monitoring", "djb.ums.email.ums_evnt_id", "")); // UMS이벤트ID(필수)
|
||||||
dataVO.setSnd_dman_dt(jsonData[0]);
|
dataVO.setSnd_dman_dt(jsonData[0]);
|
||||||
dataVO.setSnd_dman_id(this.getSndDmanId(messageRequest.getMessageType()));
|
dataVO.setSnd_dman_id(this.getSndDmanId(messageRequest.getMessageType()));
|
||||||
dataVO.setSnd_dman_sno("1");
|
dataVO.setDman_seqno(1); // 발송요청순번
|
||||||
dataVO.setEmail_titl(messageRequest.getSubject()); // 메일제목
|
dataVO.setEmail_titl(messageRequest.getSubject()); // 메일제목
|
||||||
dataVO.setCstno(propertyService.getPropertyValue("Monitoring", "djb.ums.email.cstno", "")); // 고객번호(필수)
|
dataVO.setCstno(propertyService.getPropertyValue("Monitoring", "djb.ums.email.cstno", "")); // 고객번호(필수)
|
||||||
dataVO.setSendr_emaddr(propertyService.getPropertyValue("Monitoring", "djb.ums.email.sendr_emaddr", "")); // 발신자 이메일
|
|
||||||
dataVO.setSendr_nm(propertyService.getPropertyValue("Monitoring", "djb.ums.email.sendr_nm", "")); // 발신자 이름
|
|
||||||
dataVO.setSndbk_emaddr(propertyService.getPropertyValue("Monitoring", "djb.ums.email.sndbk_emaddr", "")); // 리턴 이메일
|
|
||||||
dataVO.setRecvr_emaddr(messageRequest.getEmail()); // 수신자 이메일(필수)
|
dataVO.setRecvr_emaddr(messageRequest.getEmail()); // 수신자 이메일(필수)
|
||||||
dataVO.setRecvr_nm(messageRequest.getUsername()); // 수신자명(필수)
|
dataVO.setRecvr_nm(messageRequest.getUsername()); // 수신자명(필수)
|
||||||
dataVO.setTmplt_mpng_info(messageRequest.getMessage()); // 탬플릿매핑정보
|
dataVO.setTmplt_mpng_info(messageRequest.getMessage()); // 탬플릿매핑정보
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ public class EmailDataVO {
|
|||||||
private String snd_dman_id;
|
private String snd_dman_id;
|
||||||
|
|
||||||
/** 발송요청순번 */
|
/** 발송요청순번 */
|
||||||
private String snd_dman_sno;
|
private int dman_seqno;
|
||||||
|
|
||||||
/** 메일제목 */
|
/** 메일제목 */
|
||||||
private String email_titl;
|
private String email_titl;
|
||||||
|
|||||||
+4
-4
@@ -85,10 +85,10 @@ public class WebhookReceiveService {
|
|||||||
log.info("[Webhook] 이벤트 처리 시작 - eventType: {}", eventType);
|
log.info("[Webhook] 이벤트 처리 시작 - eventType: {}", eventType);
|
||||||
|
|
||||||
switch (eventType) {
|
switch (eventType) {
|
||||||
case "CONTROL_START":
|
case "CHECK_START":
|
||||||
handleControlStart(data);
|
handleControlStart(data);
|
||||||
break;
|
break;
|
||||||
case "CONTROL_END":
|
case "CHECK_END":
|
||||||
handleControlEnd(data);
|
handleControlEnd(data);
|
||||||
break;
|
break;
|
||||||
case "ERROR_START":
|
case "ERROR_START":
|
||||||
@@ -107,11 +107,11 @@ public class WebhookReceiveService {
|
|||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
|
|
||||||
private void handleControlStart(JsonNode data) {
|
private void handleControlStart(JsonNode data) {
|
||||||
log.info("[Webhook] CONTROL_START 처리 - data: {}", data);
|
log.info("[Webhook] CHECK_START 처리 - data: {}", data);
|
||||||
// TODO: 점검시작 처리 로직
|
// TODO: 점검시작 처리 로직
|
||||||
}
|
}
|
||||||
private void handleControlEnd(JsonNode data) {
|
private void handleControlEnd(JsonNode data) {
|
||||||
log.info("[Webhook] CONTROL_END 처리 - data: {}", data);
|
log.info("[Webhook] CHECK_END 처리 - data: {}", data);
|
||||||
// TODO: 점검종료 처리 로직
|
// TODO: 점검종료 처리 로직
|
||||||
}
|
}
|
||||||
private void handleErrorStart(JsonNode data) {
|
private void handleErrorStart(JsonNode data) {
|
||||||
|
|||||||
@@ -244,6 +244,8 @@ public class PortalApprovalManService extends BaseService {
|
|||||||
|
|
||||||
appApprovalUI.setApprovalDetail(appRequest.getReason());
|
appApprovalUI.setApprovalDetail(appRequest.getReason());
|
||||||
appApprovalUI.setClientName(appRequest.getClientName());
|
appApprovalUI.setClientName(appRequest.getClientName());
|
||||||
|
// 신청 사유는 상세 내용과 별개 항목으로도 내려준다(해지 신청 화면에서 "해지 사유"로 표기)
|
||||||
|
appApprovalUI.setRequestReason(appRequest.getReason());
|
||||||
|
|
||||||
appApprovalUI.getApprovers().forEach(approver -> {
|
appApprovalUI.getApprovers().forEach(approver -> {
|
||||||
if (approver.getUser() == null) {
|
if (approver.getUser() == null) {
|
||||||
|
|||||||
@@ -30,4 +30,7 @@ public class PortalAppApprovalUI extends PortalApprovalUI {
|
|||||||
|
|
||||||
//DELETE 승인 시 선택된 GW 처리방식 (승인 완료 건 상세 표시용)
|
//DELETE 승인 시 선택된 GW 처리방식 (승인 완료 건 상세 표시용)
|
||||||
private GwAction gwAction;
|
private GwAction gwAction;
|
||||||
|
|
||||||
|
//신청자가 입력한 사유(PTL_APP_REQUEST.REASON). 해지 신청은 사유가 필수라 별도 항목으로 노출한다.
|
||||||
|
private String requestReason;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,22 +1,40 @@
|
|||||||
package com.eactive.eai.rms.onl.apim.portalmenu;
|
package com.eactive.eai.rms.onl.apim.portalmenu;
|
||||||
|
|
||||||
import com.eactive.apim.portal.portalproperty.service.PortalPropertyService;
|
import com.eactive.apim.portal.portalproperty.service.PortalPropertyService;
|
||||||
|
import org.apache.http.client.HttpClient;
|
||||||
|
import org.apache.http.client.config.RequestConfig;
|
||||||
|
import org.apache.http.impl.client.HttpClientBuilder;
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.web.client.RestTemplate;
|
import org.springframework.web.client.RestTemplate;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
import java.util.concurrent.CancellationException;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* eapim-portal 메뉴 캐시 리로드 클라이언트 (admin → portal 내부 호출).
|
* eapim-portal 메뉴 캐시 리로드 클라이언트 (admin → portal 내부 호출).
|
||||||
*
|
*
|
||||||
* <p>호출 URL 은 PTL_PROPERTY {@code Portal / portal.internal.menu-reload-url} 로 관리한다
|
* <p>호출 URL 은 PTL_PROPERTY {@code Portal / portal.internal.menu-reload-url} 로 관리한다
|
||||||
* (기본 {@code http://127.0.0.1:39130/internal/menu/reload}).
|
* (기본 {@code http://127.0.0.1:39130/internal/menu/reload}).
|
||||||
|
* 포탈이 다중 인스턴스로 기동되는 환경을 위해 <b>콤마/세미콜론/줄바꿈</b> 으로 여러 URL 을 나열할 수 있으며,
|
||||||
|
* 나열된 모든 서버로 병렬 호출한다. 각 호출의 connect/read 타임아웃은 {@value #TIMEOUT_MS}ms 이다.
|
||||||
* portal 측은 {@code menu.internal.allow-ips} 허용 IP 목록으로 요청을 검증한다.
|
* portal 측은 {@code menu.internal.allow-ips} 허용 IP 목록으로 요청을 검증한다.
|
||||||
* 오류는 결과 Map 으로 감싸 화면에 사유를 표시한다 — 예외를 전파하지 않는다.</p>
|
* 오류는 결과 Map 으로 감싸 화면에 서버별 사유를 표시한다 — 예외를 전파하지 않는다.</p>
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
public class PortalMenuCacheClient {
|
public class PortalMenuCacheClient {
|
||||||
@@ -26,50 +44,230 @@ public class PortalMenuCacheClient {
|
|||||||
static final String PROP_GROUP = "Portal";
|
static final String PROP_GROUP = "Portal";
|
||||||
static final String PROP_RELOAD_URL = "portal.internal.menu-reload-url";
|
static final String PROP_RELOAD_URL = "portal.internal.menu-reload-url";
|
||||||
static final String DEFAULT_RELOAD_URL = "http://127.0.0.1:39130/internal/menu/reload";
|
static final String DEFAULT_RELOAD_URL = "http://127.0.0.1:39130/internal/menu/reload";
|
||||||
|
static final String PROP_DESCRIPTION =
|
||||||
|
"eapim-portal 메뉴 캐시 리로드 내부 URL. 다중 서버는 콤마(,)/세미콜론(;)/줄바꿈으로 구분";
|
||||||
|
|
||||||
|
/** 서버 1대당 connect/read 타임아웃(ms) */
|
||||||
|
static final int TIMEOUT_MS = 3000;
|
||||||
|
/** 병렬 호출 전체 대기 여유분(ms) — 스레드 시작/응답 파싱 지연 흡수 */
|
||||||
|
private static final int OVERALL_SLACK_MS = 2000;
|
||||||
|
/** 동시 호출 스레드 상한 */
|
||||||
|
private static final int MAX_PARALLELISM = 10;
|
||||||
|
|
||||||
private final PortalPropertyService portalPropertyService;
|
private final PortalPropertyService portalPropertyService;
|
||||||
private final RestTemplate restTemplate;
|
private final RestTemplate restTemplate;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public PortalMenuCacheClient(PortalPropertyService portalPropertyService, RestTemplate restTemplate) {
|
public PortalMenuCacheClient(PortalPropertyService portalPropertyService) {
|
||||||
|
this(portalPropertyService, createRestTemplateWithTimeout(TIMEOUT_MS));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 테스트용 — 타임아웃이 설정된 RestTemplate 을 직접 주입한다. */
|
||||||
|
PortalMenuCacheClient(PortalPropertyService portalPropertyService, RestTemplate restTemplate) {
|
||||||
this.portalPropertyService = portalPropertyService;
|
this.portalPropertyService = portalPropertyService;
|
||||||
this.restTemplate = restTemplate;
|
this.restTemplate = restTemplate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static RestTemplate createRestTemplateWithTimeout(int timeoutMs) {
|
||||||
|
RequestConfig requestConfig = RequestConfig.custom()
|
||||||
|
.setConnectionRequestTimeout(timeoutMs)
|
||||||
|
.setConnectTimeout(timeoutMs)
|
||||||
|
.setSocketTimeout(timeoutMs)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
HttpClient httpClient = HttpClientBuilder.create()
|
||||||
|
.setMaxConnTotal(MAX_PARALLELISM * 2)
|
||||||
|
.setMaxConnPerRoute(MAX_PARALLELISM)
|
||||||
|
.setDefaultRequestConfig(requestConfig)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
|
||||||
|
factory.setHttpClient(httpClient);
|
||||||
|
|
||||||
|
RestTemplate restTemplate = new RestTemplate();
|
||||||
|
restTemplate.setRequestFactory(factory);
|
||||||
|
return restTemplate;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return {@code {success, message, itemCount?, reloadedAt?}}
|
* 설정된 모든 포탈 서버의 메뉴 캐시를 리로드한다.
|
||||||
|
*
|
||||||
|
* @return {@code {success, message, total, successCount, failCount, itemCount?, reloadedAt?,
|
||||||
|
* servers:[{url, success, message, itemCount?, reloadedAt?, elapsedMs}]}}
|
||||||
|
* — {@code success} 는 <b>모든</b> 서버가 성공한 경우에만 true
|
||||||
*/
|
*/
|
||||||
public Map<String, Object> reload() {
|
public Map<String, Object> reload() {
|
||||||
Map<String, Object> result = new LinkedHashMap<>();
|
List<String> urls = resolveUrls();
|
||||||
String url = resolveUrl();
|
List<Map<String, Object>> servers = callAll(urls);
|
||||||
try {
|
|
||||||
@SuppressWarnings("unchecked")
|
int successCount = 0;
|
||||||
ResponseEntity<Map> response = restTemplate.postForEntity(url, null, Map.class);
|
for (Map<String, Object> server : servers) {
|
||||||
Map<String, Object> body = response.getBody();
|
if (Boolean.TRUE.equals(server.get("success"))) {
|
||||||
if (response.getStatusCode().is2xxSuccessful() && body != null && "OK".equals(body.get("result"))) {
|
successCount++;
|
||||||
result.put("success", true);
|
}
|
||||||
result.put("message", "포탈 메뉴 캐시 리로드 완료");
|
}
|
||||||
result.put("itemCount", body.get("itemCount"));
|
int failCount = servers.size() - successCount;
|
||||||
result.put("reloadedAt", body.get("reloadedAt"));
|
|
||||||
} else {
|
Map<String, Object> result = new LinkedHashMap<>();
|
||||||
result.put("success", false);
|
result.put("success", failCount == 0);
|
||||||
result.put("message", "포탈 응답 오류: " + (body == null ? response.getStatusCode() : body));
|
result.put("message", summarize(servers.size(), successCount, failCount));
|
||||||
|
result.put("total", servers.size());
|
||||||
|
result.put("successCount", successCount);
|
||||||
|
result.put("failCount", failCount);
|
||||||
|
result.put("servers", servers);
|
||||||
|
|
||||||
|
// 단일 서버 시절 응답과의 호환 — 첫 성공 서버의 값을 최상위에도 노출
|
||||||
|
for (Map<String, Object> server : servers) {
|
||||||
|
if (Boolean.TRUE.equals(server.get("success"))) {
|
||||||
|
result.put("itemCount", server.get("itemCount"));
|
||||||
|
result.put("reloadedAt", server.get("reloadedAt"));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
|
||||||
logger.error("포탈 메뉴 캐시 리로드 실패 - url: " + url, e);
|
|
||||||
result.put("success", false);
|
|
||||||
result.put("message", "포탈 호출 실패(" + url + "): " + e.getMessage());
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String resolveUrl() {
|
private String summarize(int total, int successCount, int failCount) {
|
||||||
|
if (total == 0) {
|
||||||
|
return "리로드 대상 URL 이 설정되지 않았습니다 (" + PROP_GROUP + " / " + PROP_RELOAD_URL + ")";
|
||||||
|
}
|
||||||
|
if (failCount == 0) {
|
||||||
|
return "포탈 메뉴 캐시 리로드 완료 (" + successCount + "/" + total + " 서버)";
|
||||||
|
}
|
||||||
|
if (successCount == 0) {
|
||||||
|
return "포탈 메뉴 캐시 리로드 실패 (0/" + total + " 서버)";
|
||||||
|
}
|
||||||
|
return "포탈 메뉴 캐시 리로드 일부 실패 (" + successCount + "/" + total + " 서버 성공)";
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 모든 URL 로 병렬 호출. 반환 순서는 {@code urls} 순서와 동일하다. */
|
||||||
|
private List<Map<String, Object>> callAll(List<String> urls) {
|
||||||
|
if (urls.isEmpty()) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
if (urls.size() == 1) {
|
||||||
|
return Collections.singletonList(callOne(urls.get(0)));
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Callable<Map<String, Object>>> tasks = new ArrayList<>(urls.size());
|
||||||
|
for (final String url : urls) {
|
||||||
|
tasks.add(new Callable<Map<String, Object>>() {
|
||||||
|
@Override
|
||||||
|
public Map<String, Object> call() {
|
||||||
|
return callOne(url);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ExecutorService executor = Executors.newFixedThreadPool(Math.min(urls.size(), MAX_PARALLELISM));
|
||||||
try {
|
try {
|
||||||
return portalPropertyService.getOrCreateProperty(PROP_GROUP, PROP_RELOAD_URL,
|
List<Future<Map<String, Object>>> futures =
|
||||||
DEFAULT_RELOAD_URL, "eapim-portal 메뉴 캐시 리로드 내부 URL");
|
executor.invokeAll(tasks, TIMEOUT_MS + OVERALL_SLACK_MS, TimeUnit.MILLISECONDS);
|
||||||
} catch (Exception e) {
|
|
||||||
logger.warn("리로드 URL 조회 실패 - 기본값 사용: " + DEFAULT_RELOAD_URL, e);
|
List<Map<String, Object>> results = new ArrayList<>(urls.size());
|
||||||
return DEFAULT_RELOAD_URL;
|
for (int i = 0; i < futures.size(); i++) {
|
||||||
|
String url = urls.get(i);
|
||||||
|
Future<Map<String, Object>> future = futures.get(i);
|
||||||
|
try {
|
||||||
|
results.add(future.get());
|
||||||
|
} catch (CancellationException e) {
|
||||||
|
logger.warn("포탈 메뉴 캐시 리로드 타임아웃 - url: " + url);
|
||||||
|
results.add(failure(url, "응답 시간 초과(" + TIMEOUT_MS + "ms)", TIMEOUT_MS));
|
||||||
|
} catch (ExecutionException e) {
|
||||||
|
logger.error("포탈 메뉴 캐시 리로드 실패 - url: " + url, e.getCause());
|
||||||
|
results.add(failure(url, message(e.getCause()), 0L));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
logger.error("포탈 메뉴 캐시 리로드 중단됨", e);
|
||||||
|
List<Map<String, Object>> results = new ArrayList<>(urls.size());
|
||||||
|
for (String url : urls) {
|
||||||
|
results.add(failure(url, "호출이 중단되었습니다", 0L));
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
} finally {
|
||||||
|
executor.shutdownNow();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 서버 1대 호출 — 예외를 전파하지 않고 실패 Map 으로 감싼다. */
|
||||||
|
private Map<String, Object> callOne(String url) {
|
||||||
|
long startedAt = System.currentTimeMillis();
|
||||||
|
try {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
ResponseEntity<Map> response = restTemplate.postForEntity(url, null, Map.class);
|
||||||
|
long elapsed = System.currentTimeMillis() - startedAt;
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
Map<String, Object> body = response.getBody();
|
||||||
|
if (response.getStatusCode().is2xxSuccessful() && body != null && "OK".equals(body.get("result"))) {
|
||||||
|
Map<String, Object> server = new LinkedHashMap<>();
|
||||||
|
server.put("url", url);
|
||||||
|
server.put("success", true);
|
||||||
|
server.put("message", "리로드 완료");
|
||||||
|
server.put("itemCount", body.get("itemCount"));
|
||||||
|
server.put("reloadedAt", body.get("reloadedAt"));
|
||||||
|
server.put("elapsedMs", elapsed);
|
||||||
|
return server;
|
||||||
|
}
|
||||||
|
logger.warn("포탈 메뉴 캐시 리로드 응답 오류 - url: " + url + ", status: " + response.getStatusCode()
|
||||||
|
+ ", body: " + body);
|
||||||
|
return failure(url, "포탈 응답 오류: " + (body == null ? response.getStatusCode() : body), elapsed);
|
||||||
|
} catch (Exception e) {
|
||||||
|
long elapsed = System.currentTimeMillis() - startedAt;
|
||||||
|
logger.error("포탈 메뉴 캐시 리로드 실패 - url: " + url, e);
|
||||||
|
return failure(url, message(e), elapsed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, Object> failure(String url, String message, long elapsedMs) {
|
||||||
|
Map<String, Object> server = new LinkedHashMap<>();
|
||||||
|
server.put("url", url);
|
||||||
|
server.put("success", false);
|
||||||
|
server.put("message", message);
|
||||||
|
server.put("elapsedMs", elapsedMs);
|
||||||
|
return server;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String message(Throwable t) {
|
||||||
|
if (t == null) {
|
||||||
|
return "알 수 없는 오류";
|
||||||
|
}
|
||||||
|
String msg = t.getMessage();
|
||||||
|
return (msg == null || msg.trim().isEmpty()) ? t.getClass().getSimpleName() : msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> resolveUrls() {
|
||||||
|
String raw;
|
||||||
|
try {
|
||||||
|
raw = portalPropertyService.getOrCreateProperty(PROP_GROUP, PROP_RELOAD_URL,
|
||||||
|
DEFAULT_RELOAD_URL, PROP_DESCRIPTION);
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.warn("리로드 URL 조회 실패 - 기본값 사용: " + DEFAULT_RELOAD_URL, e);
|
||||||
|
raw = DEFAULT_RELOAD_URL;
|
||||||
|
}
|
||||||
|
List<String> urls = parseUrls(raw);
|
||||||
|
return urls.isEmpty() ? parseUrls(DEFAULT_RELOAD_URL) : urls;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 콤마/세미콜론/줄바꿈으로 구분된 URL 목록을 파싱한다.
|
||||||
|
* {@code #} 로 시작하는 줄은 주석으로 무시하고, 중복 URL 은 최초 순서만 남긴다.
|
||||||
|
*/
|
||||||
|
static List<String> parseUrls(String raw) {
|
||||||
|
if (raw == null || raw.trim().isEmpty()) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
Set<String> urls = new LinkedHashSet<>();
|
||||||
|
for (String token : raw.split("[,;\\r\\n]")) {
|
||||||
|
String url = token.trim();
|
||||||
|
if (url.isEmpty() || url.startsWith("#")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
urls.add(url);
|
||||||
|
}
|
||||||
|
return new ArrayList<>(urls);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+8
@@ -1,11 +1,13 @@
|
|||||||
package com.eactive.eai.rms.onl.manage.comm.error;
|
package com.eactive.eai.rms.onl.manage.comm.error;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import com.eactive.apim.portal.jpa.PersonalDataEncryptConverter;
|
||||||
import com.eactive.eai.rms.common.base.BaseService;
|
import com.eactive.eai.rms.common.base.BaseService;
|
||||||
import com.eactive.eai.rms.data.entity.onl.adapter.AdapterGroupService;
|
import com.eactive.eai.rms.data.entity.onl.adapter.AdapterGroupService;
|
||||||
import com.eactive.eai.rms.data.entity.onl.inbound.error.InboundErrorInfoSearch;
|
import com.eactive.eai.rms.data.entity.onl.inbound.error.InboundErrorInfoSearch;
|
||||||
@@ -21,6 +23,8 @@ public class InboundErrorInfoManService extends BaseService {
|
|||||||
|
|
||||||
private AdapterGroupService adapterGroupService;
|
private AdapterGroupService adapterGroupService;
|
||||||
|
|
||||||
|
private final PersonalDataEncryptConverter encryptConverter = new PersonalDataEncryptConverter();
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public InboundErrorInfoManService(InboundErrorInfoService inboundErrorInfoService,
|
public InboundErrorInfoManService(InboundErrorInfoService inboundErrorInfoService,
|
||||||
InboundErrorInfoUIMapper inboundErrorInfoUIMapper, AdapterGroupService adapterGroupService) {
|
InboundErrorInfoUIMapper inboundErrorInfoUIMapper, AdapterGroupService adapterGroupService) {
|
||||||
@@ -44,6 +48,10 @@ public class InboundErrorInfoManService extends BaseService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (StringUtils.isNotBlank(ui.getBzwkDataCtnt())) {
|
||||||
|
ui.setBzwkDataCtnt(encryptConverter.convertToEntityAttribute(ui.getBzwkDataCtnt()));
|
||||||
|
}
|
||||||
|
|
||||||
return ui;
|
return ui;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+7
-6
@@ -97,10 +97,13 @@ public class EaiMsgManService extends OnlBaseService {
|
|||||||
EAIMessageEntity eaiMessageEntity = tuple.get(QEAIMessageEntity.eAIMessageEntity);
|
EAIMessageEntity eaiMessageEntity = tuple.get(QEAIMessageEntity.eAIMessageEntity);
|
||||||
String nonMotivRoutUriName = tuple.get(QRouting.routing.nonmotivrouturiname);
|
String nonMotivRoutUriName = tuple.get(QRouting.routing.nonmotivrouturiname);
|
||||||
String psvIntfaCdSticName = tuple.get(QServiceMessageEntity.serviceMessageEntity.psvintfacdsticname);
|
String psvIntfaCdSticName = tuple.get(QServiceMessageEntity.serviceMessageEntity.psvintfacdsticname);
|
||||||
|
String psvSysAdptrBzwkGroupName = tuple
|
||||||
|
.get(QServiceMessageEntity.serviceMessageEntity.psvsysadptrbzwkgroupname);
|
||||||
|
|
||||||
EAIMessageUI eaiMessageUI = eaiMessageUIMapper.toVoWithoutChildren(eaiMessageEntity);
|
EAIMessageUI eaiMessageUI = eaiMessageUIMapper.toVoWithoutChildren(eaiMessageEntity);
|
||||||
eaiMessageUI.setNonMotivRoutUriName(nonMotivRoutUriName);
|
eaiMessageUI.setNonMotivRoutUriName(nonMotivRoutUriName);
|
||||||
eaiMessageUI.setPsvIntfaCdSticName(psvIntfaCdSticName);
|
eaiMessageUI.setPsvIntfaCdSticName(psvIntfaCdSticName);
|
||||||
|
eaiMessageUI.setPsvSysAdptrBzwkGroupName(psvSysAdptrBzwkGroupName);
|
||||||
return eaiMessageUI;
|
return eaiMessageUI;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -114,16 +117,14 @@ public class EaiMsgManService extends OnlBaseService {
|
|||||||
Map<String, Object> map = new HashMap<>();
|
Map<String, Object> map = new HashMap<>();
|
||||||
|
|
||||||
EAIMessageEntity eaiMessageEntity = tuple.get(QEAIMessageEntity.eAIMessageEntity);
|
EAIMessageEntity eaiMessageEntity = tuple.get(QEAIMessageEntity.eAIMessageEntity);
|
||||||
String nonMotivRoutUriName = tuple.get(QRouting.routing.nonmotivrouturiname);
|
String psvSysAdptrBzwkGroupName = tuple
|
||||||
String psvIntfaCdSticName = tuple.get(QServiceMessageEntity.serviceMessageEntity.psvintfacdsticname);
|
.get(QServiceMessageEntity.serviceMessageEntity.psvsysadptrbzwkgroupname);
|
||||||
|
|
||||||
map.put("EAIBZWKDSTCD", eaiMessageEntity.getEaibzwkdstcd());
|
map.put("EAIBZWKDSTCD", eaiMessageEntity.getEaibzwkdstcd());
|
||||||
map.put("EAISVCNAME", eaiMessageEntity.getEaisvcname());
|
map.put("EAISVCNAME", eaiMessageEntity.getEaisvcname());
|
||||||
map.put("EAISVCDESC", eaiMessageEntity.getEaisvcdesc());
|
map.put("EAISVCDESC", eaiMessageEntity.getEaisvcdesc());
|
||||||
map.put("SVCMOTIVUSEDSTCD", eaiMessageEntity.getSvcmotivusedstcd());
|
map.put("GSTATSYSADPTRBZWKGROUPNAME", eaiMessageEntity.getGstatsysadptrbzwkgroupname());
|
||||||
map.put("PSVINTFACDSTICNAME", psvIntfaCdSticName);
|
map.put("PSVSYSADPTRBZWKGROUPNAME", psvSysAdptrBzwkGroupName);
|
||||||
map.put("NONMOTIVROUTURINAME", nonMotivRoutUriName);
|
|
||||||
map.put("FLOWCTRLROUTNAME", eaiMessageEntity.getFlowctrlroutname());
|
|
||||||
|
|
||||||
String eaisevrdstcd = codeService
|
String eaisevrdstcd = codeService
|
||||||
.findCodeName("INOUT_TYPE", eaiMessageEntity.getEaisevrdstcd())
|
.findCodeName("INOUT_TYPE", eaiMessageEntity.getEaisevrdstcd())
|
||||||
|
|||||||
@@ -109,6 +109,9 @@ public class EAIMessageUI {
|
|||||||
@JsonProperty("PSVINTFACDSTICNAME")
|
@JsonProperty("PSVINTFACDSTICNAME")
|
||||||
private String psvIntfaCdSticName;
|
private String psvIntfaCdSticName;
|
||||||
|
|
||||||
|
@JsonProperty("PSVSYSADPTRBZWKGROUPNAME")
|
||||||
|
private String psvSysAdptrBzwkGroupName;
|
||||||
|
|
||||||
@JsonProperty("svcAll")
|
@JsonProperty("svcAll")
|
||||||
private List<ServiceMessageUI> serviceMessages;
|
private List<ServiceMessageUI> serviceMessages;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -453,6 +453,6 @@
|
|||||||
INSERT INTO $schemaId$.TSEAITR10
|
INSERT INTO $schemaId$.TSEAITR10
|
||||||
( LOGPRCSSSEQNO, SEQNO, SERVICENAME ,COMMAND,LOUTNAME,RECVDATA,RECVAMNDHMS,PRCSSRSLT, PRCSSRSLTCMNT )
|
( LOGPRCSSSEQNO, SEQNO, SERVICENAME ,COMMAND,LOUTNAME,RECVDATA,RECVAMNDHMS,PRCSSRSLT, PRCSSRSLTCMNT )
|
||||||
VALUES
|
VALUES
|
||||||
( #logPrcssSeqno#, #seqno#, #serviceName# ,#command#,#loutName#,#recvData#,#recvAmndHMS#,#prcssRslt#, #prcssRsltCmnt# )
|
( #logPrcssSeqno#, $schemaId$.TSEAITR10_SEQNO.NEXTVAL, #serviceName# ,#command#,#loutName#,#recvData#,#recvAmndHMS#,#prcssRslt#, #prcssRsltCmnt# )
|
||||||
</statement>
|
</statement>
|
||||||
</sqlMap>
|
</sqlMap>
|
||||||
|
|||||||
@@ -723,6 +723,7 @@ eaiMessage.failSts = Failover Status
|
|||||||
eaiMessage.failoverWhether = Failover whether or not
|
eaiMessage.failoverWhether = Failover whether or not
|
||||||
eaiMessage.flowCtrlRoutName = FlowControl Routing Name
|
eaiMessage.flowCtrlRoutName = FlowControl Routing Name
|
||||||
eaiMessage.gstaSysAdptBzwkGroupName = Activation interface type
|
eaiMessage.gstaSysAdptBzwkGroupName = Activation interface type
|
||||||
|
eaiMessage.gstatSysAdptr = Activation Adapter
|
||||||
eaiMessage.hdrConClaCd = Header Control Classification Code
|
eaiMessage.hdrConClaCd = Header Control Classification Code
|
||||||
eaiMessage.ifIdKeyVal = IF identification key value
|
eaiMessage.ifIdKeyVal = IF identification key value
|
||||||
eaiMessage.ifSvcMsgList = Interface Service Message List
|
eaiMessage.ifSvcMsgList = Interface Service Message List
|
||||||
@@ -739,6 +740,7 @@ eaiMessage.nextSvcPrcOrd = Next Service Process Order
|
|||||||
eaiMessage.nextSvcSeq = Next service process sequence
|
eaiMessage.nextSvcSeq = Next service process sequence
|
||||||
eaiMessage.outRoutNm = Outbound Routing Name
|
eaiMessage.outRoutNm = Outbound Routing Name
|
||||||
eaiMessage.proOrder = Processing order
|
eaiMessage.proOrder = Processing order
|
||||||
|
eaiMessage.psvSysAdptr = Passive Adapter
|
||||||
eaiMessage.psvintfacdsticName = Passive Interface Type
|
eaiMessage.psvintfacdsticName = Passive Interface Type
|
||||||
eaiMessage.queueName = Queue Name
|
eaiMessage.queueName = Queue Name
|
||||||
eaiMessage.refClsNm = Reference Class Name
|
eaiMessage.refClsNm = Reference Class Name
|
||||||
|
|||||||
@@ -852,6 +852,7 @@ eaiMessage.failSts = Failover ?
|
|||||||
eaiMessage.failoverWhether = Failover ?
|
eaiMessage.failoverWhether = Failover ?
|
||||||
eaiMessage.flowCtrlRoutName = FlowControl Routing
|
eaiMessage.flowCtrlRoutName = FlowControl Routing
|
||||||
eaiMessage.gstaSysAdptBzwkGroupName = 1st Adapter
|
eaiMessage.gstaSysAdptBzwkGroupName = 1st Adapter
|
||||||
|
eaiMessage.gstatSysAdptr = 1st Adapter
|
||||||
eaiMessage.hdrConClaCd = Header Control Division
|
eaiMessage.hdrConClaCd = Header Control Division
|
||||||
eaiMessage.ifIdKeyVal = IF Identification key value
|
eaiMessage.ifIdKeyVal = IF Identification key value
|
||||||
eaiMessage.ifSvcMsgList = Interface Service Message List
|
eaiMessage.ifSvcMsgList = Interface Service Message List
|
||||||
|
|||||||
@@ -888,6 +888,7 @@ eaiMessage.failSts = FailOver\uC5EC\uBD80
|
|||||||
eaiMessage.failoverWhether = failover\uC5EC\uBD80
|
eaiMessage.failoverWhether = failover\uC5EC\uBD80
|
||||||
eaiMessage.flowCtrlRoutName = FlowControl
|
eaiMessage.flowCtrlRoutName = FlowControl
|
||||||
eaiMessage.gstaSysAdptBzwkGroupName = \uAE30\uB3D9\uC778\uD130\uD398\uC774\uC2A4 \uC720\uD615
|
eaiMessage.gstaSysAdptBzwkGroupName = \uAE30\uB3D9\uC778\uD130\uD398\uC774\uC2A4 \uC720\uD615
|
||||||
|
eaiMessage.gstatSysAdptr = \uAE30\uB3D9\uC5B4\uB311\uD130
|
||||||
eaiMessage.hdrConClaCd = \uD5E4\uB354\uC81C\uC5B4\uAD6C\uBD84\uCF54\uB4DC
|
eaiMessage.hdrConClaCd = \uD5E4\uB354\uC81C\uC5B4\uAD6C\uBD84\uCF54\uB4DC
|
||||||
eaiMessage.ifIdKeyVal = EAI \uC2DD\uBCC4\uD0A4\uAC12
|
eaiMessage.ifIdKeyVal = EAI \uC2DD\uBCC4\uD0A4\uAC12
|
||||||
eaiMessage.ifSvcMsgList = OUTBOUND \uC11C\uBE44\uC2A4 \uBA54\uC2DC\uC9C0 \uBAA9\uB85D
|
eaiMessage.ifSvcMsgList = OUTBOUND \uC11C\uBE44\uC2A4 \uBA54\uC2DC\uC9C0 \uBAA9\uB85D
|
||||||
@@ -904,6 +905,7 @@ eaiMessage.nextSvcPrcOrd = \uB2E4\uC74C\uC11C\uBE44\uC2A4\uCC98\uB9AC
|
|||||||
eaiMessage.nextSvcSeq = \uB2E4\uC74C\uC11C\uBE44\uC2A4\uCC98\uB9AC\uC21C\uC11C
|
eaiMessage.nextSvcSeq = \uB2E4\uC74C\uC11C\uBE44\uC2A4\uCC98\uB9AC\uC21C\uC11C
|
||||||
eaiMessage.outRoutNm = Outbound\uB77C\uC6B0\uD305\uBA85
|
eaiMessage.outRoutNm = Outbound\uB77C\uC6B0\uD305\uBA85
|
||||||
eaiMessage.proOrder = \uCC98\uB9AC\uC21C\uC11C
|
eaiMessage.proOrder = \uCC98\uB9AC\uC21C\uC11C
|
||||||
|
eaiMessage.psvSysAdptr = \uC218\uB3D9\uC5B4\uB311\uD130
|
||||||
eaiMessage.psvintfacdsticName = \uC218\uB3D9\uC778\uD130\uD398\uC774\uC2A4 \uC720\uD615
|
eaiMessage.psvintfacdsticName = \uC218\uB3D9\uC778\uD130\uD398\uC774\uC2A4 \uC720\uD615
|
||||||
eaiMessage.queueName = \uD050\uBA85
|
eaiMessage.queueName = \uD050\uBA85
|
||||||
eaiMessage.refClsNm = \uCC38\uACE0\uD074\uB798\uC2A4\uBA85
|
eaiMessage.refClsNm = \uCC38\uACE0\uD074\uB798\uC2A4\uBA85
|
||||||
|
|||||||
Reference in New Issue
Block a user