List에서 불필요한 item을 제거하기 위해 loop를 돌리게 되면 제거 후 size가 맞지 않는 일로 인해 null point exception을 만나기가 쉽다.

이럴 경우 제대로 된 방법이 무엇인지는 모르지만...

실제로 돌려보고 Exception이 나지 않은 방법을 찾아 정리 차원에서 남겨 둔다.


검색해서 참고한 URL은 https://stackoverflow.com/questions/17279519/removing-items-from-list-in-java/17279565#17279565?newreg=0dee1db24aaa4154a0cebdc173ed5aeb


List<Object> toRemove = new ArrayList<Object>();

for(Object a: list){

if(a.getXXX().equalsIgnoreCase("AAA")){

toRemove.add(a);

}

}

list.removeAll(toRemove);


다른 방법들은 다 해 봤지만 null point exception 발생 함.


저작자 표시 비영리 변경 금지
신고

WRITTEN BY
체리필터
프로그램 그리고 인생...

받은 트랙백이 없고 , 댓글이 없습니다.
secret
Site-mesh의 decorators.xml 파일에서 excludes를 정의해서 사용하려 했지만
여전희 decorator 파일이 적용 되는 상황이 발생했다.
여기 저기 구글링 해 봤지만 내 검색 능력의 한계인가 잘 찾질 못했다.
결국 사내 아는 분에게 문의해서 원인을 알게 되었다.


sitemesh.xml decorators.xml


위의 decorators.xml에서 uninstall 부분만 decorator를 적용하지 않으려 했지만 처음에는 적용 되지 않았고,
이에 sitemesh.xml의 아래 부분이 추가 되면서 문제가 해결 되었다.

<property name="decorators" value="/WEB-INF/decorators.xml" />
<excludes file="${decorators}" />

삽질은 정말 해도 해도 끝이 없는거 같다.
신고

WRITTEN BY
체리필터
프로그램 그리고 인생...

받은 트랙백이 없고 , 댓글이 없습니다.
secret
실 서비스 도중에 대량의 작업을 동기식으로 작업하려면 부담이 되는 경우가 많다.
이럴 경우에는 비동기식으로 작업을 하게 되는데, 보통 Queue에 작업해야 할 목록을 집어 넣어두고, 나중에 Cosumer가 해당 작업을 하도록 만드는 것이 일반적이다.
이런 작업을 하는데 유용한 도구가 ActiveMQ이며 이번 주소록 프로젝트를 하면서 ActiveMQ를 사용하게 되어 정리차원에서 블로그에 올려본다.

설치하기 이전에 우선 환경을 셋팅해야 한다.

JDK는 1.5.x 버젼 이상 설치되어 있어야 하며, " JAVA_HOME" 환경 변수는 JDK가 설치된 경로로 잡혀 있어야 한다. Maven은 1.0.2 이상 설치되어 있어야 한다.(Maven은 소스 설치 또는 개발자 버젼 설치를 위해 필요한 듯...)
또한 관련 JAR 파일들은 미리 classpath에 있어야 한다.
따라서 Maven을 사용한다면 dependencies 아래 아래와 같이 추가하면 된다.



<!-- For Active MQ -->
<dependency>
    <groupId>org.apache.activemq</groupId>
    <artifactId>activemq-core</artifactId>
    <version>5.2.0</version>
</dependency>
<dependency>
    <groupId>org.apache.activemq</groupId>
    <artifactId>activemq-web</artifactId>
    <version>5.2.0</version>
</dependency>
<dependency>
    <groupId>org.apache.xbean</groupId>
    <artifactId>xbean-spring</artifactId>
    <version>3.3</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
    <version>2.5.6.SEC01</version>
</dependency>

 환경 셋팅을 다했다면 ActiveMQ를 다운로드 해서 설치해야 한다. 다운로드는 http://activemq.apache.org/download.html 에서 다운 받을 수 있으며, 현재 기준으로 안정 버젼은 5.3.0이다.

설치는 다운로드 받은 파일을 적당한 곳에 풀어주면 된다.

설치 후 ActiveMQ를 실행 시킨다.

cd [activemq_install_dir]
bin\activemq

위와 같이 하던가 아니면 설치 디렉토리의 activemq.bat 파일을 더블클릭 해도 된다.
Unix(Linux) 환경에서는 아래와 같이 하면 된다.

cd [activemq_install_dir]
bin/activemq

OR

bin/activemq > /tmp/smlog  2>&1 &;
Note: /tmp/smlog may be changed to another file name.

ActiveMQ의 자세한 Start 방법은 http://activemq.apache.org/version-5-getting-started.html#Version5GettingStarted-StartingActiveMQ 를 참고하면 된다.

ActiveMQ를 실행 후 제대로 돌고 있는지 확인하기 위해서는 61616 포트를 확인해 보면 된다.

Windows

netstat -an|find "61616"
  TCP    0.0.0.0:61616          0.0.0.0:0              LISTENING

Unix(Linux)

netstat -an|grep 61616
tcp        0      0 :::61616                    :::*                        LISTEN 

위와 같이 61616 포트를 Listen 하고 있다면 제대로 ActiveMQ가 실행 되고 있는 것이다.
또한 위와 같이 ActiveMQ가 실행되고 있는 것이 확인되면 아래의 url로 접근해서 Queue의 상태를 확인해 볼 수 있다.

http://localhost:8161/admin

물론 해당 서버가 로컬이 아니라면 위의 localhost 도메인을 적절히 수정해야 할 것이다.

기본적으로 ActiveMQ를 위와 같은 방식으로 띄운다면 ActiveMQ가 설치된 디렉토리의 conf 디렉토리 밑에 있는 activemq.xml 파일을 가지고 뜬다. 하지만 원하는 디렉토리 밑에 있는 activemq.xml을 참조하도록 하기 위해서는 아래와 같이 띄우면 된다.

activemq설치디렉토리/bin/activemq xbean:file:원하는소스가 있는 디렉토리

activemq.xml에서는 기본적으로 아래와 같은 셋팅을 하면 된다.


policyEntry 부분에 queue 이름만 정확히 넣어 주고 여기서 셋팅한 이름을 applicationContext.xml 파일에서 사용하면 된다.
jetty 부분은 admin으로 모니터링 할 내용을 적어 둔 것이다.
덧. activemq.base는 상단에서 단순히 properties 파일 선언하고 해당 부분에서 ActiveMQ가 설치된 디렉토리를 지정한 것이다.

* applicationContext.xml 파일의 설정


위와 같이 설정이 모두 마쳐 졌다면 프로그램을 만들 차례이다.
우선 가장 기본이 되는 리스너는 다음과 같은 형식으로 만들어 주면 된다.


위 클래스는 주소를 수정할 경우 registerQueue 메소드를 호출해서 Queue에 한개의 아이디를 쌓고, Listener에서 Queue에 데이터가 들어오면 pullFromQueueAndModifyAddress 메소드를 호출해서 수정한 아이디의 주소를 이용하여 친구들 주소들 모두를 수정해 주는 것이다.

우선 applicationContext.xml에서 선언한 jmsTemplate 관련 setter를 선언해 주고 기본이 되는 2가지 메소드를 만들어 주면 된다.
registerQueue 메소드는 Queue에 등록하는 메소드이며 메소드 등록 시 jmsTemplate를 이용하면 된다. 해당 메소드는 별도의 외부 클래스에서 호출해 주는 것이므로 알아서 테스트 해 보면 될 것이다.
Queue에 데이터가 등록되면 Listener가 알아서 감지하고 pullFromQueueAndModifyAddress 메소드가 실행 된다.(applicationContext.xml의 listener list에 선언한 부분)
안의 비즈니스 로직은 알아서 만들면 되는 것이고 이렇게 되면 http://localhost:8161/admin/queues.jsp 에서 해당 내용이 제대로 적용 되었는지 확인해 볼 수 있다.

보통 Queue에 Data가 쌓이게 되면 바로 바로 Consumer가 작동하게 되므로 서버를 Debug 모드로 돌려 놓고 BreakPoint를 찍어 놓았다면 registerQueue를 실행하는 즉시 디버거가 작동하게 될 것이다.

덧. 백업 용도로 정신 없이 작성하다 보니 내가 써 놓고도 내가 무슨 말이지 모르겠다 ^^ 적당히 알아서 들으시면 될 것 같다. 삽질은 프로그램의 기본 ^^
덧2. ActiveMQ의 설정 및 시작 방법 등 자세한 내용은 http://users.handysoft.co.kr/~wsko/articles/activemq-guide/index.html에 더 잘 나온 것 같다.



신고

WRITTEN BY
체리필터
프로그램 그리고 인생...

받은 트랙백이 없고 , 댓글이 없습니다.
secret
매일 프로그램 삽질은 하고 있지만 이번 건은 유난히 더 삽질이 길었다.
3일 동안 아무런 일도 못하고 이 일에만 매달렸다.
다른 일을 하긴 해야 하지만, 개발자 자존심에 해결하지 못하고 넘어가기에도 뭐 하고...
결국에는 해결하게 되었지만 아무것도 아닌 원인 때문에 해결하고도 짜증이 난다.

증상은 다음과 같다.




소스는 간단하다.
그냥 특정 쿠키를 생성한 다음 response에 실어 보내는 것이다.

그런데 로컬과 서버의 결과물이 달랐다.

* 로컬의 결과물
cookieKey1=bla...bla...;
cookieKey2=bla...bla...;

* 서버의 결과물
cookieKey1="bla...bla...";
cookieKey2="bla...bla...";

둘 간의 차이점은 value 앞 뒤로 쌍따옴표(")가 있느냐 없느냐이다.
큰 차이가 아닐지 모르지만 인증 관련된 작업을 다루는데 있어서 해당 값으로 인해 로그인이 되기도 하고 안되기도 하는 부분이라서 매우 골치 아픈 부분이었다.

소스를 이리도 뜯어보고 저리도 뜯어 봤지만 해결은 되지 않았고,
Googling을 아무리 해 봐도 답은 나오지 않았다.(내 능력 부족 -.-;;)

결국 회사 내 다른 분의 도움을 얻어 로컬과 서버의 tomcat 버젼의 차이때문에 생기는 것임을 알게 되었고 서버의 tomcat 버젼을 5.5.27로 downgrade해서 문제를 해결하게 되었다

관련된 내용은 http://tomcat.apache.org/tomcat-5.5-doc/changelog.html 의 46587 에서 확인해 볼 수 있다.

신고

WRITTEN BY
체리필터
프로그램 그리고 인생...

트랙백이 하나이고 , 댓글이 없습니다.
secret
프로젝트를 진행하면서 BTS로 _, %로 검색시 검색이 제대로 안된다는 내용이 등록되었다.
해당 내용을 해결하기 위해 구글링 하던 도중 아래와 같은 내용을 찾게 되었다.

http://okjsp.pe.kr/seq/2372

'_', '%'와 같은 문자들이 검색을 하기 위한 wild 문자로 사용되지 않고 리터럴 문자로 사용되기 위해서는 뒤에 escape '\' 와 같이 사용해 주어야 한다는 것이다.
즉 다음과 같이 사용하면 되는 것이다.

LIKE '%검색어\_\%% escape '\'

사용하고 있는 DB는 CUBRID 였으며, 위와 같이 할 경우 잘 동작 되었다.

위 내용을 수정하면서 SQL Injection 위험이 있던 '%$keyword$%' 부분도 '%#keyworkd#%'로 바꾸게 되었다.
하지만 이 과정 중에 ibatis가 자체적으로 #keyword#를 'keyword'로 바꾸기 때문에 결과에서는 '%'keyword'%'가 되므로 수정해 주어야 했다.
MySQL이라면 CONCAT과 같은 함수를 써서 다음과 같이 하면 된다.

LIKE CONCAT('%', #keyword# '%')

하지만 CUBRID에는 CONCAT 함수가 없다. 관련해서 또다시 검색해 보니 Java에서 String을 이어 붙이기 하는 것과 같은 방법을 사용하면 되었다.
즉 CUBRID에서는 다음과 같이 하면 된다.

LIKE '%' + #keyword# + '%'

오늘도 삽질을 통해 또 하나의 깨달음을 얻게 되었다.
신고

WRITTEN BY
체리필터
프로그램 그리고 인생...

받은 트랙백이 없고 , 댓글 하나 달렸습니다.
  1. ㅋㅋㅋ, 지금 저한테 필요한 내용 ㅋㅋㅋ
secret