2017년 10월 24일 화요일

"Result" 속성은 이미 정의되었습니다. 를 사용하여 이 충돌을 해결하십시오.

cxf로 웹서비스 클라이언트 자동 생성시 아래와 같은 에러 발생.
"Result" 속성은 이미 정의되었습니다. <jaxb:property>를 사용하여 이 충돌을 해결하십시오.

wsdl element로 java 파일을 만들때, element 명으로 java 파일명을 생성하는 데, 중복된 경우 발생하는 에러이다.

-autoNameResolution 옵션으로 자동으로 변경 된다고 하는데, 왜인지 해당 옵션이 먹지 않는다.

 

binding 수동으로 지정해서 생성하면 된다고 하는 데,  잘 안됨.

그냥 wsdl 을 xml 로 저장하고 element 명을 수정하여 처리 하였다.

 

 

참조

 

cxf 웹서비스 클라이언트 자동 생성 파일 타입 지정.

cxf 로 웹서비스 클라이언트 생성시 생성되는 파일이 EUC-KR로 생성된다.
-encoding UTF-8 를 사용하여 생성되는 파일 타입을 강제로 지정이 가능하다.
해당 옵션을 wsdl2java.bat 넣고 이클립스에서 생성시에는 해당옵션이 적용되지 않는다.
이클립스에서는 wsdl2java.bat를 사용하지 않고 org.apache.cxf.tools.wsdlto.WSDLToJava 를 바로 사용하기 때문이다.

어쩔수 없이 이클립스 console에 출력되는 wsdl2java... command를 복사해서
-encoding UTF-8 를 붙여서 수동으로 생성 후 소스에 붙여 넣었다.

2017년 8월 4일 금요일

PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification 에러 해결법

mvn clean install 명령어를 실행하려고 했더니, 에러 메시지가 난다.
PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification

 

문제의 원인은 JAVA에서 인증서를 신뢰하지 않아서 발생 하는 문제.

나의 경우는 회사에서만 발생하는 에러이다.

왜냐면...

회사에서 나의 활동을 감시하기 위하여 'SSL PRISM Cerificate Installer (ARA Networks Co.,Ltd)' 프로그램을 강제로 설치하도록 했기 때문이다.

설치안하면 인터넷이 안된다.  ㅡㅡ;
쩝... 어째든 해결 방법은 다음과 같다.

아래의 경로로 가면
'C:\Program Files (x86)\ARA Networks Co.,Ltd\SSL PRISM Certificate Installer'

SSLPrism.crt 파일이 있다. 이것을 자바의 ca가 저장 되어 있는 'C:\Program Files\Java\jdk1.8.0_131\jre\lib\security'로 복사 해준다.

그래고 아래 명령어로 인증서를 추가 해준다.
C:\Program Files\Java\jdk1.8.0_131\jre\lib\security>keytool -keystore cacerts -importcert -alias sslprism -file SSLPrism.crt

 

패스워드를 물어보는데, 기본패스워드는 'changeit' 이다.

그리고 y.
mvn clean install 명령을 다시 실행하면 정상적으로 동작 한다.

 

ps.

아래 명령어로 ssl 무시하고 하려고 했지만, 안 됐다.
mvn clean install -Dmaven.wagon.http.ssl.insecure=true -Dmaven.wagon.http.ssl.allowall=true -Dmaven.wagon.http.ssl.ignore.validity.dates=true

https://stackoverflow.com/questions/21252800/how-to-tell-maven-to-disregard-ssl-errors-and-trusting-all-certs

 

참고.
https://gs.saro.me/#!m=elec&p=1&jn=772
https://docs.microsoft.com/ko-kr/azure/java-add-certificate-ca-store

2017년 7월 6일 목요일

StringUtils의 isEmpty, isBlank 분석.

자바에서 Null 포함 빈값을 체크 할 때, StringUtils의 isEmpty 나 isBlank를 사용한다.
isEmpty는 "", null 일 경우 true를 리턴한다.
isBlank는 "", null, " " 일 경우 true를 리턴한다.

해당 메소드가 어떻게 동작하는 지 알아 봤다.

소스
isEmpty가 동작하는 방식은 간단하다.
        public static boolean isEmpty(String str) {
return str == null || str.length() == 0;
}

null 이거나, length 가 0 일경우를 체크 한다.

 

 

isBlank는 조금 더 복잡하다.
        public static boolean isBlank(String str) {
int strLen;
if (str == null || (strLen = str.length()) == 0) {
return true;
}
for (int i = 0; i < strLen; i++) {
if ((Character.isWhitespace(str.charAt(i)) == false)) {
return false;
}
}
return true;
}

첫번째는 isEmpty와 같지만 스페이스를 체크하기 위해 for문을 돈다.

 

 

간혹 StringUtils 라이브러리가 없고, 추가 할 수 없는 경우 참고 하면 좋을 것 같다.

2017년 6월 30일 금요일

오라클 EXCEPTION 진행 문제.

CREATE OR REPLACE PROCEDURE PROCEDURE1
AS

V_CNTR_NO VARCHAR2(13) ;
V_ITEM_CD VARCHAR2(13) ;

BEGIN

DBMS_OUTPUT.PUT_LINE('시작.') ;

BEGIN
SELECT CNTR_NO INTO V_CNTR_NO FROM TB_OD_CNSGN_FEE;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('계약번호가 없습니다.') ;
WHEN TOO_MANY_ROWS THEN
DBMS_OUTPUT.PUT_LINE('계약번호가 두건 이상입니다.') ;
END;

DBMS_OUTPUT.PUT_LINE('중간.') ;

BEGIN
SELECT ITEM_CD INTO V_ITEM_CD FROM TB_OD_CNSGN_FEE;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('아이템코드가 없습니다.') ;
WHEN TOO_MANY_ROWS THEN
DBMS_OUTPUT.PUT_LINE('아이템코드가 두건 이상입니다.') ;
END;


DBMS_OUTPUT.PUT_LINE('끝.') ;

EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('TOP EXCEPTION.') ;
END PROCEDURE1;

-------실행결과----------------------------
계약번호가 두건 이상입니다.
아이템코드가 두건 이상입니다.
끝.
프로세스가 종료되었습니다.

보통 EXCEPTION 처리를 위와 같이 중첩 블록을 사용하였다.
문제는 EXCEPTION이 발생하여도 해당 블록만 멈추고 다음으로 계속 진행을 한다.
자바와는 다르다.
그래서 각 블록마다 RAISE_APPLICATION_ERROR를 발생시키거나, 메인 블록만 남기는 방법을 선택해야 한다.

2017년 6월 1일 목요일

우클릭시 text 복사

우클릭시 '복사' DIV 나타나서 클릭시 우클릭 위의 TEXT를 복사하는 스크립트이다.

원했던 건 우클릭하면 바로 복사 하려고 하였으나,
왜 그런지 document.execCommand("copy"); 가 동작하지 않는다.
그래서 click 이벤트로 발생하기 위해 '복사'div 를 생성하였다.
	function copyToClipboard(value, showNotification, notificationText) {
var $temp = $("<input>");
$("body").append($temp);
$temp.val(value).select();
document.execCommand("copy");
$temp.remove();

if (typeof showNotification === 'undefined') {
showNotification = true;
}
if (typeof notificationText === 'undefined') {
notificationText = "Copied to clipboard";
}

var notificationTag = $("div.copy-notification");
if (showNotification && notificationTag.length == 0) {
notificationTag = $("<div/>", { "class": "copy-notification", text: notificationText });
$("body").append(notificationTag);

notificationTag.fadeIn("slow", function () {
setTimeout(function () {
notificationTag.fadeOut("slow", function () {
notificationTag.remove();
});
}, 10);
});
}
}

var copyData = "";
//$(".context-menu-one").on("contextmenu", function(event) {
$("table").on("contextmenu", function(event) {
event.preventDefault();
$("div.custom-menu").remove();
copyData = $.trim(event.target.textContent);

$("<div class='custom-menu'>복사</div>")
.appendTo("body")
.css({top: event.pageY + "px", left: event.pageX + "px"})
.on("click", function(event) {
event.preventDefault();
copyToClipboard(copyData);
copyData = "";
$("div.custom-menu").remove();
});

$("body").click(function (){
$("div.custom-menu").remove();
});
});


 
/* 우측 클릭 '복사' */
.custom-menu {
z-index:1000;
position: absolute;
background-color:#C0C0C0;
border: 1px solid black;
padding: 2px;
border-radius: 5px;
}

.copy-notification {
color: #ffffff;
background-color: rgba(0,0,0,0.8);
padding: 20px;
border-radius: 30px;
position: fixed;
top: 50%;
left: 50%;
width: 150px;
margin-top: -30px;
margin-left: -85px;
display: none;
text-align:center;
}

참조

2017년 5월 29일 월요일

datepicker 버튼 추가(당일, 1주일, 1개월, 3개월)



 

 

 

 

 

 

 

 

 

from 절과 to절이 있는 부분을 datepicker로는 만들수가 없다.

datepicker 달력 하단에 당일, 1주일, 1개월, 3개월 버튼을 넣어서

from절과 to절에 넣도록 했다.

 
function fnDatepickerFromToDateRangeSet(startId, endId, searchFnName){

$("#"+startId).datepicker( "option", "beforeShow",
function (input) {
fnDatepickerRangeSet(input,startId,endId,1,searchFnName);
}
);

$("#"+endId).datepicker( "option", "beforeShow",
function (input) {
fnDatepickerRangeSet(input,startId,endId,2,searchFnName);
}
);
//버튼 위치 input 안으로 넣도록 함.
$(".ui-datepicker-trigger").css({"vertical-align": "middle", "cursor": "pointer", "padding-left": "2px"}).addClass("box_date_btn");

}


//하단 당월,1주일,1개월,3개월 버튼 추가 - 함수.
//이 함수 자체는 달력이 보여질때 실행되고 하단 버튼 클릭시는 'click: function' 부분에서 실행됨을 주의!
function fnDatepickerRangeSet(input, startId, endId, startEndChk, searchFnName) {
setTimeout(function () {

var dateText = ["당일", "1주일", "1개월", "3개월"];
var dateRange = ["0d", "-7d", "-1m", "-3m"];
var buttonPane = $(input).datepicker("widget").find(".ui-datepicker-buttonpane");

for(i=0;dateText.length > i; i++ ){
$("<button>", { text: dateText[i], value:dateRange[i], executeFn:searchFnName,
//하단 버튼을 클릭시에는 여기 'click: function'이 실행된다.
click: function (eventData) {
$("#"+startId).datepicker('setDate', eventData.currentTarget.value);
$("#"+endId).datepicker('setDate', '0d');
jQuery(input).datepicker('hide');
var execFn = eventData.currentTarget.getAttribute('executeFn');
if(execFn){
eval(execFn);
}

}
}).appendTo(buttonPane).addClass("ui-datepicker-clear ui-state-default ui-priority-primary ui-corner-all");
}

//오늘 버튼 숨김
$(input).datepicker("widget").find(".ui-datepicker-current").hide();



}, 1)
}