<< 5월 2008 | | 7월 2008 >>

tomcat의 강제 종료(shutdown) 방법

catalina.sh파일을 열어보면 CATALINA_PID라는 변수를 활용하여 프로세스를 kill하는 것을 볼 수 있습니다. 그것을 활용하는 방법입니다.

우선 먼저 .bash_profile 에 다음과 같은 내용을 추가합니다.
shell>vi ~/.bash_profile
CATALINA_PID=$CATALINA_HOME/bin/.tomcat_pid;export CATALINA_PID
shell>source ~/.bash_profile
shell>./shutdown.sh -force
shell>./startup.sh
startup.sh 를 실행하면 $CATALINA_HOME/bin/.tomcat_pid 파일에 톰캣의 pid가 저장됩니다.
그리고 종료할때 shutdown.sh -force를 실행하면 정상적인 종료가 안될 경우  .catalina_pid 에 저장된 tomcat pid 정보로 다시 강제로 kill하게 됩니다.
./catalina.sh stop보다는 shutdown.sh 커맨드를 활용하여 중단해 주세요. 물론 구동도 ./catalina.sh start보다는 startup.sh 커맨드를 활용하시구요. ^^

우동 한그릇

이 <우동 한 그릇>을 쓴 일본의 여류작가 구리 료헤이는 홋카이도(북해도)의 가난한 집 딸로 태어났답니다. 학교를 마친 후 병원에서 10년을 근무했는데 그 후 온갖 직업을 전전하다가 마침내 동화작가가 되었다고 합니다.

구리 료헤이는 주로 어린이를 위한 구연용 동화 작품을 창작했습니다. 그러다 <베 짜는 공주>, <기적이 울리다> 등의 명작을 썼는데, 그녀의 대표작이라면 이 <우동 한 그릇>이라 할 수 있습니다.

송파 구민회관에서 우동한그릇을 했답니다. 아이들도 많았구요.
근데 아이들이 많다보니 시끄러워서 집중이 안되긴 했죠 ^^. 그래도 이해가 갑니다.
무대는 옆으 그림과 같이 우동을 만드는 카운터가 있는 주방과 우동을 먹을 수 있는 테이블과 조그만 의자들이 전부였습니다. 거기서 등장인물들(우동집 남자주인, 우동집 여자주인, 아이의 엄마, 첫째 형아, 둘째 쭌이)의 대화를 통해 잔잔한 감동을 몰고 왔습니다.

찬바람이 부는 섣달 그믐날, 일본 홋카이도의 우동집 '북해정'에서의 일입니다. 손님이 모두 돌아가 막 문을 닫으려던 때였어요.
출입문이 힘없이 열리더니 낡은 체크무늬 반코트를 입은 여자가 두 아이를 데리고 들어왔습니다.
"어서 오세요."
두 아이를 데리고 들어온 그 어머니는 머뭇머뭇 말했습니다.
"저……. 우동……. 일 인분만 시켜도 괜찮을까요?"
세 명이 들어와 일 인분만 시켰지만, 북해정 여주인은 아주 친절하고 힘있는 목소리로 응해주었습니다. 그리고 난로 옆의 2번 테이블로 안내했어요.
"우동, 일 인분!"
주문을 받은 남자 주인은 손님 세 사람을 슬쩍 보고는,
"네!"
하고 대답했어요. 마음씨가 따뜻한 그는 일 인분의 우동 한 덩어리와 거기에 반 덩어리를 더 넣어 삶았습니다.
테이블에 나온 많은 양의 우동을 가운데 두고, 이마를 맞대고 먹는 세 사람. 그들의 이야기가 카운터 있는 곳까지 희미하게 들렸습니다.
"맛있네요."
라는 형의 목소리.
"엄마도 잡수세요."
하며 한 가닥의 국수를 집어 어머니의 입으로 가져가는 동생.
이윽고 그들은 150엔의 우동 값을 지불했습니다.
"맛있게 먹었습니다."
북해정 여주인 역시 잊지 않고 경쾌하게 대답했어요.
"고맙습니다, 새해엔 복 많이 받으세요!"
그렇게 섣달 그믐날은 저물었습니다.
그런데 그들은 일년에 딱 한 번, 섣달 그믐날이면 어김없이 찾아왔어요. 늘 우동 한 그릇을 셋이서 먹고는 집으로 돌아갔습니다.
북해정 주인은 이제 해마다 섣달 그믐날 밤을 기다리게 되었어요. 그날이면 머뭇거리며 찾아와 우동 일 인분을 나눠먹고 가는 가족이 있는 것입니다.
우동 값이 올라도 그들을 위해 오르기 전의 우동 값으로 바꿔 놓았습니다. 2번 테이블도 예약 석으로 지정해 자리를 비워 두었습니다.
그렇게 십수 년의 세월이 흘렀어요.
어느 섣달 그믐날, 사람들로 시끄러운 북해정 안으로 오버를 손에 든 정장 차림의 두 청년이 들어왔습니다. 그리고 어머니가 머리를 숙이며 들어와서는 두 청년 사이에 섰습니다.
어머니가 정중하고도 조용하게 말했어요.
"저……. 우동……. 삼 인분입니다만……. 괜찮겠죠?"
그 말을 들은 여주인은 금방 그들을 알아보았어요. 십수 년의 세월을 넘어 그들이 다시 찾아온 것입니다.
당황해 하면서도 반가워하는 북해정 사람들에게 막내아들이 말했어요.
"우리는 14년 전 섣달 그믐날 밤, 셋이서 일 인분의 우동을 주문했던 가족입니다. 그때의 한 그릇 우동에 용기를 얻어……."
그 막내아들은 이어서 말했어요. 사람들에게 학교에서의 작문 이야기를 들려주었습니다.
그 작문에는, 아버지가 교통사고를 내고 죽는 바람에 빚이 많다는 것, 그래서 어머니가 고생하고 있다는 것, 해마다 12월 31일이면 셋이서 먹는 한 그릇의 우동이 그렇게 맛있었다는 것.
북해정 아주머니의 "고맙습니다! 새해엔 복 많이 받으세요!"라는 말이 "지지 말아라! 힘내! 살아갈 수 있어!"라는 뜻으로 들려 무척이나 힘이 됐다는 것.
그리고 자신도 손님들에게 그런 힘을 줄 수 있는 우동집 주인이 되고 싶다는 작문 내용이었습니다.
이런 얘기를 들은 북해정 주인은 감동의 눈물을 흘렸지요.
그들은 많이 변했어요. 한 그릇의 우동을 부끄럽다고 생각하는 그 마음이 더 부끄러운 것이라 깨달았다는 형은 의사가 되었습니다. 우동집 주인을 꿈꾸던 동생은 은행원이 되었고요.
그들은 십 년 만에 다시 북해정을 찾아온 것입니다. 이젠 우동 세 그릇을 주문했어요. 자신들을 위해 십 년 간 예약되어 있던 2번 테이블에서 말입니다.
나중에 북해정 주인은 가게 인테리어를 바꿀 때 어머니와 두 아들이 앉았던 2번 테이블을 중앙에 두었어요.
그 테이블을 보며 자신들의 자극제로 삼기로 했습니다. 그리고 주위 사람들에게 이 <우동 한 그릇> 이야기를 수시로 전했습니다.
늘 그렇지만, 북해정 주변의 사람들은 섣달 그믐날이면 각자 자기 집으로 돌아가는 대신 북해정에 모였어요. 서로 음식을 나눠먹으며 아직 보이지 않는 어머니와 두 아들을 기다렸습니다.
불행한 경험과 가난한 삶은 우리를 우울하게 합니다. 우리를 괴롭히며 절망에 빠지게 합니다. 그대로 침몰해 버릴 수도 있었던 한 가족에게 희망을 주는 일! 음식점 주인의 마음을 감동시켜 그 감동을 이웃에게 전하도록 하고, 그 이웃 사람들의 마음을 바꿔 준 우동 한 그릇!

정말 하잘것 없이 보이는 우동 한그릇에 담긴 사람들의 이야기를 통해 우리들의 심금을 울렸고 자신의 과거를 돌아보게 하고, 마음을 다시 잡게 하는 것이었습니다.
가슴이 찐한 것은 왜일까요?
가난했지만 희망을 갖고 살아가는 모습을 보면서, 풍족하지는 않았지만 세식구가 우동 한그릇을 나눠먹으로면 보여주었던 정(가족애)
이런 정을 잊지 않을려고 가게 주인이 그들을 위해 남겨둔 2번 테이블..
오고 가는 대화속에 깊고, 잔잔한 감동의 전율이 어느새 제 마음속으로 들어오네요.
아니나 다를까 아내의 눈에는 눈물이 고여있습니다.
조금이나마 살아가는데 있어서 마음의 정화의 시간을 갖게 되어 나름 즐거운 시간이었습니다.
연출가는 김동수씨인데 이분이 김동수 컴퍼니를 운영하면서 후학들을 가르치시더군요. 대학로에서 정기적으로 공연을 갖는다고 합니다. 관심있으신 분들은 한번 들러보세요.
마음이 풍족해 질 것입니다.

[Tips- Spring, hibernate] 커넥션 풀 유지하기

기본적으로 mysql은 8시간 이후에 동작하지 않는 커넥션은 종료시킵니다. 그래서 커넥션 풀이 비정상 상태가 될 확률이 있어 아래와 같은 설정이 필요하게 됩니다. 기본적으로 데이터 소스는 dbcp, c3p0 두개 중에 하나를 사용하시면 되고, hibernateProperties에 c3p0 속성을 추가해주면 됩니다.
한번 적용해보세요. 가끔 TOMCAT과 MySQL 간의 CLOSE_WAIT가 발생하는 경우도 예방할 수 있습니다.

#The number of seconds the server waits for activity on a connection before closing it.
wait_timeout=28800
#The number of seconds the server waits for activity on an interactive connection before closing it.
interactive_timeout=28800
<bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName"
value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<property name="maxActive" value="30"/>
<property name="maxIdle" value="10"/>
<property name="maxWait" value="20000"/>
<property name="logAbandoned" value="true"/>
<property name="removeAbandoned" value="true"/>
<property name="removeAbandonedTimeout" value="60"/>
<property name="validationQuery" value="${jdbc.validationQuery}" />
<property name="testOnBorrow" value="true" />
<property name="testOnReturn" value="true" />
</bean>
혹은

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="driverClass" value="${jdbc.driverClassName}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<property name="acquireRetryAttempts" value="10"></property>
<property name="preferredTestQuery" value="SELECT 1;"></property>
<property name="testConnectionOnCheckin" value="true"></property>
<property name="testConnectionOnCheckout" value="false"></property>
<property name="maxIdleTime" value="300"></property>
<property name="idleConnectionTestPeriod" value="30"></property>
</bean>
<bean id="hibernateProperties"
class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="properties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
<prop key="hibernate.hbm2ddl.auto">
${hibernate.hbm2ddl.auto}</prop>
<prop key="jdbc.fetch_size">50</prop>
<prop key="jdbc.batch_size">25</prop>
<prop key="hibernate.cache.use_query_cache">true</prop>
<prop key="hibernate.cache.provider_class">
org.hibernate.cache.EhCacheProvider</prop>
<prop key="hibernate.query.substitutions">
true 1,false 0</prop>
<prop key="hibernate.c3p0.initialPoolSize">10</prop>
<prop key="hibernate.c3p0.minPoolSize">10</prop>
<prop key="hibernate.c3p0.maxPoolSize">50</prop>
<prop key="hibernate.c3p0.acquireIncrement">2</prop>
<prop key="hibernate.c3p0.timeout">10</prop>
<prop key="hibernate.c3p0.max_statement">50</prop>
<!-- dataSource가 c3p0 일경우 생략 -->
<prop key="hibernate.c3p0.testConnectionOnCheckin">
true</prop>
<!-- dataSource가 c3p0 일경우 생략 -->
<prop key="hibernate.c3p0.testConnectionOnCheckout">
false</prop>
<prop key="hibernate.c3p0.maxStatementsPerConnection">
5</prop>
<!-- dataSource가 c3p0 일경우 생략 -->
<prop key="hibernate.c3p0.maxIdleTime">300</prop>
<prop key="hibernate.c3p0.maxConnectionAge">14400</prop>
<prop key="hibernate.c3p0.acquireRetryAttempts">10</prop>
<prop key="hibernate.c3p0.preferredTestQuery">
SELECT 1;</prop>
<!-- dataSource가 c3p0 일경우 생략 -->
<prop key="hibernate.c3p0.idleConnectionTestPeriod">
300</prop>
</props>
</property>
</bean>

PS : 위의 설정의 dataSource부분에서 com.mchange.v2.c3p0.ComboPooledDataSource 라이브러리를 활용할 경우에는 c3p0 - JDBC3 Connection and Statement Pooling을 다운받아서 WEB-INF/lib에 카피해야함.

C에서 디버깅용으로 로그 남기기

예전에 C 프로그램 디버깅용으로 간단하게 사용하던 방법입니다.
물론 아래 소스를 수정해서 파일로그로 남기고, 설정으로 properties파일에서 읽어오면  Log4j 방식과 비슷하네요 ^^. log4cxx 가 있긴 하지만요 ^^.

아래는 샘플링 소스입니다.

1. 로깅을 위한 간단한 소스 : a.c
#include <stdio.h>

#define LOG_NONE 0
#define LOG_ERROR 1
#define LOG_WARN 2
#define LOG_INFO 3
#define LOG_LEVEL LOG_WARN


// 로그 레벨별로 관리
int log(char *msg, int level){
if (LOG_LEVEL >= level) {
printf("LOG %d: %s\n", level, msg);
}

return 0;
}

int main(int argc, char** argv){
printf("Hi Log Test!\n");

log("정말 에러났어 얼렁 찾아봐!", LOG_ERROR);
log("워닝이여, 나중에 시간나면 한번 봐~.", LOG_WARN);
log("흐미! 빨랑 테스트 끝났으면 지워버려.", LOG_INFO);

return 0;
}

2. 실행 결과
LOG_WARN 밑으로는 로그가 안찍히니깐 디버깅용으로 예전부터 썻던 방법입니다. ^^
[mimul.com]/home/mimul/> ./a
Hi Log Test!
LOG 1: 정말 에러났어 얼렁 찾아봐!
LOG 2: 워닝이여, 나중에 시간나면 한번 봐~.
태그 :

Mysql Tunning Helper

최소한 일주일 이상 Mysql을 운영한 다음 해당 스크립트를 받아서 실행해보면 성능 튜닝을 위한 설정 기능들(미약한 부분)을 제안해 줍니다.
물론, 완벽하게 지원은 안되지만, 최소한의 안전 장치로서 괜찮은 듯 보입니다.

1. Script 다운로드
 - wget http://day32.com/MySQL/tuning-primer.sh

2. 파일 퍼미션 변경
 - chmod 755 tuning-primer.sh

3. 실행
 - ./tuning-primer.sh

4. 실행 결과물을 Mysql에 적용
태그 :

[perl] 메일 발송 클라이언트

먼저 메일 발송을 위해서는 많이 쓰는 라이브러리인 Email-Date-Format-1.002과 MIME-Lite-3.021를 설치한 다음 발송 perl 스크립트를 작성하시면 됩니다.

1. Email-Date-Format 설치

다운 사이트 : http://search.cpan.org/dist/Email-Date-Format/
>perl Makefile.PL
>make
>make test
PERL_DL_NONLAZY=1 /usr/bin/perl "-MExtUtils::Command::MM"
"-e" "test_harness(0, 'blib/lib', 'blib/arch')" t/*.t
t/basic...........ok
1/3 skipped: test only useful in US/Eastern, -0400, not +0900
t/pod-coverage....skipped
all skipped: Test::Pod::Coverage 1.08 required for testing POD coverage
t/pod.............skipped
all skipped: Test::Pod 1.14 required for testing POD
All tests successful, 2 tests and 1 subtest skipped.
Files=3, Tests=3, 0 wallclock secs ( 0.13 cusr + 0.05 csys = 0.18 CPU)
>make install
Perl 설치 디렉토리인 /opt/perl_32/lib/site_perl/5.8.8 여기에 설치됨

2. MIME-Lite 설치

다운 사이트 : http://search.cpan.org/dist/MIME-Lite/
>perl Makefile.PL
>make
>make test
PERL_DL_NONLAZY=1 /usr/bin/perl "-MExtUtils::Command::MM"
"-e" "test_harness(0, 'blib/lib', 'blib/arch')" t/*.t
t/addrs...........ok
t/data............ok
t/head............ok
t/parts...........ok
t/pod-coverage....skipped
all skipped: Test::Pod::Coverage 1.08 required for testing POD coverage
t/pod.............skipped
all skipped: Test::Pod 1.14 required for testing POD
t/types...........#
#Interaction with MIME::Types has not been tested
#as it doesn't seem to be present.
t/types...........ok
t/verify..........ok
All tests successful, 2 tests skipped.
Files=8, Tests=43, 0 wallclock secs ( 0.52 cusr + 0.16 csys = 0.68 CPU)
>make install

Perl 설치 디렉토리인 /opt/perl_32/lib/site_perl/5.8.8 여기에 설치됨

3. 메일 발송 클라이언트
#!/usr/bin/perl

use MIME::Lite;
use Net::SMTP;

### Adjust sender, recipient and your SMTP mailhost
my $from_address = 'pepsi@mimul.com';
my $to_address = 'pepsi@paran.com';
my $mail_host = 'mimul.com';

### Adjust subject and body message
my $subject = '메일 테스트 ...';
my $message_body = "파일이 하나 첨부되었삼";

### Adjust the filenames
my $my_file_path = 'MIME-Lite-3.021.tar.gz';
my $my_file_zip = 'MIME-Lite-3.021.tar.gz';

### Create the multipart container
my $msg = MIME::Lite->new (
From => $from_address,
To => $to_address,
Subject => $subject,
Type =>'multipart/mixed'
) or die "Error creating multipart container: $!\n";

### Add the text message part
$msg->attach (
Type => 'TEXT',
Data => $message_body
) or die "Error adding the text message part: $!\n";

### Add the ZIP file
$msg->attach (
Type => 'application/zip',
Path => $my_file_path,
Filename => $my_file_zip,
Disposition => 'attachment'
) or die "Error adding $my_file_path: $!\n";

### Send the Message
MIME::Lite->send('smtp', $mail_host, Timeout=>60);
$msg->send;

[Perl] 간단한 소켓 클라이언트

파일에 커맨드(전송할 전문)를 넣고 그 파일을 읽어서 서버로 전문을 전송하는 perl 스크립트입니다. 간단한 배치형태로 운용이 가능합니다.
유용하게 쓰세요.
#!/usr/bin/perl -w
use IO::Socket;

my $file = './20080204.txt';
open(F, $file);
my @lines = <F>;
close(F);

my $hostname = "mimul.com";
my $port = "49999";
my $content = '';
open(FF, ">>batch.log");
foreach $content(@lines)
{
my $remote = IO::Socket::INET->new(PeerAddr => $hostname, PeerPort => $port,
Proto => 'tcp', Timeout => 10);

print FF "$content";
$remote->autoflush(1);
print $remote "$content\n";
while (<$remote>)
{
print FF;
}
close $remote;
}
close(FF);
태그 :

Open Source 기반의 차트 프로그램

1. JFreeChart
 - 지원 기능 : pie charts (2D and 3D), bar charts (horizontal and vertical, regular and stacked), line charts, scatter plots, time series charts, high-low-open-close charts, candlestick plots, Gantt charts, combined plots, thermometers
 - 지원 언어 : Java 지원
 - 예제 사이트 : http://www.jfree.org/jfreechart/samples.html

2. Cewolf
 - 지원 기능 : Line [XY], [3D] Pie, [3D] Horizonal Bar, [3D] Vertical [XY] Bar, [3D] Stacked Vertical Bar, Area [XY], Scatter Plot, Candlestick, High Low, Gantt, Overlaid, Combined
 - 지원 언어 : Java 지원
 - 예제 사이트 : http://cewolf.sourceforge.net/new/demo.html

3. PHP/SWF Charts
 - 지원 기능 : Line, Column, Stacked column,  Floating column, 3D column, Stacked 3D column, Parallel 3D column, Pie, 3D Pie, Bar, Stacked bar,  Floating bar, Area, Stacked area, Candlestick, Scatter, Polar, Mixed, Composite, Joined
 - 지원 언어 : PHP + Flash (swf), SP, CFML, Perl언어에서도 지원
 - 예제 사이트 : http://www.maani.us/charts/index.php?menu=Gallery

4. Open Flash Chart(플래시 기반)
 - 지원 기능 : Data Lines, Bar Chart, 3D Bar Chart, Glass Bar Chart, Fade Bar Chart, Sketch Bars, Area Chart, Bars + Lines, Pie Chart, Pie Chart Links, Scatter Chart, Mixed Scatter, High Low Close, Candle
 - 지원 언어 : 플래시 기반으로 Java, Perl, Python, Ruby and Rails, php, .net 지원
 - 예제 사이트 : http://teethgrinder.co.uk/open-flash-chart/index.php

5. AmCharts(플래시 기반)
 -  지원 기능 : Animated or static, Value axis, Linear, logarithmic value axis scale, bullets, Clickable columns/bars, Gradient fills, plot area Axis
 - 지원 언어 :  플래시 기반으로 PHP, .NET, Java, Ruby on Rails, Perl, ColdFusion 언어 지원
 - 예제 사이트 : http://www.amcharts.com/column

6. FusionCharts(플래시 기반)
 - 지원 기능 : 다양한 기능 지원함
 - 지원 언어 : cross-browser, cross-platform flash chart로서 ASP.NET, ASP, PHP, JSP, ColdFusion, Ruby on Rails, simple HTML pages 지원
 - 예제 사이트 : http://www.fusioncharts.com/Free/Gallery.asp?gMenuItemId=3

7. Flot
 - 지원 기능 : Line 기능 등 기본적인 기능에 줌 등 다양한 옵션을 줄 수 있음
 - 지원 언어 : Javascript + jQuery로 구성되어 있어 웹기반 언어는 모두 지원, Cross Browser지원
 - 예제 사이트 : http://people.iola.dk/olau/flot/examples/

8. Flotr
 - 지원 기능 : Basic Axis, Basic Bar, Basic Legend, Mouse Track, Mouse Zoom, JSON Data
 - 지원 언어 : Javascript + Prototype 1.6.0.2로 구성되어 있어 웹기반 언어는 모두 지원, Cross Browser지원
 - 예제 사이트 : http://www.solutoire.com/experiments/flotr/examples/basic.html

9. PlotKit
 - 지원 기능 : HTML Canvas: Safari 2+, Opera 9+, Firefox 1.5+, IE 6 (in emulated mode), SVG: Opera 9+, Firefox 1.5+ (see note), IE6 with Adobe SVG
 - 지원 언어 : Javascript + MochiKit 1.3로 구성되어 있어 웹기반 언어는 모두 지원, Cross Browser지원
 - 예제 사이트 : http://media.liquidx.net/js/plotkit-tests/svg-sweet.html

10. Emprise JavaScript Charts
 - 지원 기능 : Interactive, Axis Scaling, Auto Zooming, Scrolling, Stackable Series, Multiple Chart Types, Ajax-Driven Data, Compatible, Plugin Free, Customizable
 - 지원 언어 : Javascript로 구현되어 있고 Cross Browser지원
 - 예제 사이트 : http://www.ejschart.com/examples/index.php

11. Visifire
 - 지원 기능 : 실버 라이트 설치되면 다양한 차트 기능이 지원됨
 - 지원 언어 : Silverlight Charts
 - 예제 사이트 : http://www.visifire.com/silverlight_charts_gallery.php

JSCalendar를 활용한 일자 조회

JSCalendar 1.0을 기반으로 하여 생년월일이나 일자등을 UI에서 선택할 수 있도록 해주는 Javascript입니다.
다운 사이트는 dynarch이며 jscalendar-1.0다운 받아서 카피한 다음에 필요한 js와 css를 삽입하여 원하는 화면을 구성할 수 있습니다.

1. 화면 UI

2. 사용 방법

<!-- main calendar program -->
<script type="text/javascript" src="/calendar.js"></script>
<!-- language for the calendar -->
<script type="text/javascript" src="/lang/calendar-ko.js"></script>
<!-- the following script defines the Calendar.setup helper function,
which makes adding a calendar a matter of 1 or 2 lines of code. -->
<script type="text/javascript" src="/calendar-setup.js"></script>
<!-- calendar stylesheet -->
<link rel="stylesheet" type="text/css" media="all"
href="/calendar-white.css" title="white" />
.........
 <td><input type="text" name="dob" id="dob" readonly="1" /></td>
 <td><img src="img.gif" id="f_trigger_c"
style="cursor: pointer; border: 1px solid red;" title="Date selector"
      onmouseover="this.style.background='red';"
onmouseout="this.style.background=''" /></td>
<script type="text/javascript">
    Calendar.setup({
        inputField     :    "dob",     // id of the input field
        ifFormat       :    "%Y-%m-%d", // format of the input field
        button         :    "f_trigger_c",// trigger for the calendar(button ID)
        align          :    "Tl",       // alignment (defaults to "Bl")
        singleClick    :    true
    });
</script>

Hibernate hbm2ddl 툴

Hibernate hbm2ddl은 Hibernate 매핑 설정 정보를 가지고 데이터 베이스 스키마의 create, update, validate 기능을 허용하는 기능입니다. 즉, DB의 테이블을 자동으로 생성할 수도 있고 생성 및 DROP, 필드 정보 변경만 가할 수 있는 기능입니다.

1. 사용하기 위한 설정 정보
<bean id="hibernateProperties"
class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="properties">
<prop key="hibernate.dialect">
org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="jdbc.fetch_size">50</prop>
<prop key="jdbc.batch_size">25</prop>
<prop key="hibernate.cache.use_query_cache">true</prop>
<prop key="hibernate.cache.provider_class">
org.hibernate.cache.EhCacheProvider</prop>
<prop key="hibernate.query.substitutions">true 1,false 0</prop>
</property>
</bean>

2. hibernate.hbm2ddl.auto 의미
  • create : 무조건 테이블를 생성하고 classpath에 import.sql이 있을 경우 import.sql을 구동해 준다.
  • create-drop : create기능과 같고 추가적으로 테이블 drop기능까지 부여된다.
  • update : 테이블이 없을 경우 테이블 생성하고 있을 경우 테이블의 칼럼 구조 변경되면 변경까지 가능
  • validate : 테이블 스키마의 Validation기능만 제공

모드

     import.sql 테이블 구조 변경

비고

update

불가

가능

 

create

가능

가능


create-drop

가능

가능

SessionFactory가 닫힐때 DROP

validate

불가

불가

 


초기 개발시에는 create-drop, create, update를 많이 사용하실겁니다. 운영 모드에서는 validate를 사용하는 경우가 많죠.

Velocity 소개

1. 주석 사용
## 로 시작하면 한 줄 코멘트
#* 로 시작하고 *#로 끝나면, 여러 줄 코멘트
#** 로 시작하고 *#로 끝나면, 블록 코멘트.

2. 레퍼런스
$(variable) : 컨텍스트에서 제공되는 변수에 대한 레퍼런스
$(variable.property) : 속성에 대한 레퍼런스
$(cariable.method(arg)) : 메소드에 대한 레퍼런스

예)
$date.format("yyyy-MM-dd", $createTime)

3. 디렉티브
#set : 레퍼런스의 값 설정
#if/#elseif/#else : 조건문 제어
#foreach : 객체 리스트에 댛란 반복 제어
#include : 벨로시티로 파싱되지 않은 로컬 파일 출력
#parse : 벨로시티로 파싱된 로컬 템플릿 출력
#stop : 템플릿 엔진의 동작 정지
#macro : 반복적으로 사용될 VM(velocimacro)

예)
*. set
#set ($val = 1234567)

*. if/elseif/else
#if( $foo == $bar ) -> 등치 연산자
#if( $foo == 42 )
#if( $foo == "bar" )
#if( !$foo ) -> Boolean NOT

*. foreach
$allPages가 List나 Array인 경우
#foreach( $page in $allPages)
   $page
#end

$allPages가 Map이나 Hashtable일 경우

#foreach( $key in $allPages.keySet())
   $key -> $allPages.get($key)
#end

*. include
Velocity에 의해 파싱되지 않는 로컬 파일(들)을 렌더링
#include ("a.html")

*. parse
Velocity에 의해 파싱되는 로컬 템플릿을 렌더링
#parse ("me.vm")

*. macro
편리한 함수를 만들어서 사용 가능함
#**
 * General purpose date formatter. Need to be careful of whitespace.
 * @param dateFormat Date format to be used (see java.text.SimpleDateFormat).
 * @param date Date object to be formatted (see java.util.Date).
 *#
#macro(formatDate $dateFormat $date )
  $utils.formatDate($date, $dateFormat)
#end

4. toolbox.xml(Velocity Tool)을 활용한 사용자 정의 오브젝트의 사용
toolbox.xml에 사용자 정의 클래스를 적용하여 vtl에서 사용할 수 있다. getXX(), setXX(), isXX() 형태로 정의되었을 경우 가능

예)
*. Date Tool
org.apache.velocity.tools.generic.DateTool class를 추가함
$date.format("yyyy-MM-dd HH:mm:ss", $myDate)   -> 2008-06-03 19:11:09

*. Number Tool
org.apache.velocity.tools.generic.NumberTool class를 추가함
$number.format("currency", $val)   -> ₩1,234,567
$number.format("integer", $val)    -> 1,234,567

*. Escape Tool
org.apache.velocity.tools.generic.EscapeTool를 추가함
$javascript                  -> I'm Mimul
$esc.javascript($javascript) -> I\'m Mimul

태그 :

Gtalk Chat 구현 하기

Smack.jar이라는  Java XMPP client library를 가지고 Google Talk Client 어플리케이션을 개발할 수 있습니다. 웹 채팅 인터페이스를 만들수도 있죠.
아래는 응용한 소스를 공유합니다.

1. 응용 소스
package com.mimul.common.util;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.jivesoftware.smack.Chat;
import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.MessageListener;
import org.jivesoftware.smack.PacketCollector;
import org.jivesoftware.smack.Roster;
import org.jivesoftware.smack.RosterEntry;
import org.jivesoftware.smack.RosterListener;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.filter.PacketFilter;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.packet.Presence;

public class GtalkClient
{
public List<RosterEntry> getOnlineEntries(XMPPConnection connection){
List<RosterEntry> onlineEntries = new ArrayList<RosterEntry>();
Roster roster = connection.getRoster();
roster.setSubscriptionMode(Roster.SubscriptionMode.accept_all);
List<RosterEntry> entries = new ArrayList<RosterEntry>();
entries.addAll(roster.getEntries());
for (RosterEntry entry:entries) {
if(roster.getPresence(entry.getUser()).getType() ==
Presence.Type.available) {
onlineEntries.add(entry);
}
}
return onlineEntries;
}

public static void main(String[] args) {
GtalkClient gtalk = new GtalkClient();
ConnectionConfiguration connConfig =
new ConnectionConfiguration("talk.google.com",
5222, "gmail.com");
XMPPConnection connection = new XMPPConnection(connConfig);
try {
connection.connect();
System.out.println("Connected to " + connection.getHost());
} catch (XMPPException ex) {
System.out.println("Failed to connect to " +
connection.getHost());
System.exit(1);
}
try {
connection.login("hahojin", "password");
System.out.println("Logged in as " + connection.getUser());
Presence presence = new Presence(Presence.Type.available);
connection.sendPacket(presence);
Roster roster = connection.getRoster();
PacketFilter myFilter = new PacketFilter() {
public boolean accept(Packet packet) {
return true;
}
};

PacketCollector collector =
connection.createPacketCollector(myFilter);
roster.addRosterListener(new RosterListener(){
public void entriesAdded(Collection<String> addresses) {

}
public void entriesDeleted(Collection<String> addresses) {
// TODO Auto-generated method stub
}

public void entriesUpdated(Collection<String> addresses) {
// TODO Auto-generated method stub
}
public void presenceChanged(Presence presence) {

}});
while(true) {
Packet packet = collector.nextResult();
if(packet instanceof Message) {
Message msg = (Message) packet;
for (RosterEntry e:gtalk.getOnlineEntries(connection)) {
if (StringUtils.isNotBlank(msg.getFrom()) &&
msg.getFrom().indexOf(e.getUser())!=-1) {
continue;
}
System.out.println("online user:" + e.getUser());
Chat chat = connection.getChatManager().createChat(
e.getUser(), new MessageListener(){
public void processMessage(Chat chat,
Message message) {
//chat.sendMessage("got it.");
}});
chat.sendMessage(msg.getFrom() + ":" +
msg.getBody());
}
}
}
} catch (XMPPException ex) {
System.out.println("Failed to log in as " +
connection.getUser());
System.exit(1);
}
System.out.println("Press enter to disconnect");
try {
System.in.read();
} catch (IOException ex) {
}
connection.disconnect();
}
}

2. 참조 문서
 - http://www.igniterealtime.org/builds/smack/docs/latest/documentation/
태그 :