<?xml version="1.0" encoding="utf-8" ?>
<?xml-stylesheet href="http://rss.egloos.com/style/blog.xsl" type="text/xsl" media="screen"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
<channel>
	<title>namKees</title>
	<link>http://namkee.egloos.com</link>
	<description>남기씨의 기분 나쁜 아침은 음악 중독을 야기했다.</description>
	<language>ko</language>
	<pubDate>Wed, 02 May 2007 07:11:35 GMT</pubDate>
	<generator>Egloos</generator>
	<image>
		<title>namKees</title>
		<url>http://pds3.egloos.com/logo/200701/12/95/c0043595.jpg</url>
		<link>http://namkee.egloos.com</link>
		<width>80</width>
		<height>80</height>
		<description>남기씨의 기분 나쁜 아침은 음악 중독을 야기했다.</description>
	</image>
  	<item>
		<title><![CDATA[ MS-SQL Stored Procedure 만들기 ]]> </title>
		<link>http://namkee.egloos.com/3367643</link>
		<guid>http://namkee.egloos.com/3367643</guid>
		<description>
			<![CDATA[ 
  원본 출처<br />
http://taeyo.pe.kr/lecture/10_ADO/SP01.asp<br />
http://taeyo.pe.kr/lecture/10_ADO/SP02.asp<br />
<br />
<table style="width: 533px; height: 3232px;" cellspacing="0"><tbody><tr height="25"><td style="border-right: 1px solid buttonface; border-bottom: 1px solid buttonface; padding-right: 20px; padding-left: 20px;" bgcolor="white"><br />
</td></tr><tr><td style="border-right: 1px solid buttonface; border-bottom: 1px solid buttonface; padding: 20px;"><br />
</td>		</tr>		<tr>			<td style="border-right: 1px solid rgb(203, 203, 203); padding-left: 20px;">	<table style="width: 528px; height: 3240px;" border="0">  <tbody><tr>    <td style="padding-bottom: 20px; padding-top: 20px;" valign="top"> <p>강좌 전 태오의 잡담&gt;</p>      <p>            		이 강좌는 ASP나 ASP.NET을 다루려는 개발자들이 데이터베이스와 관련하여 반드시 알고있어야 할 부분중에 하나인 Stored Procedure 에 대한 이야기입니다.		사실, 이 내용은 Taeyo's Advanced ASP(정보문화사)에 존재하는 내용입니다만 여러분이 ADO.NET을 접하기 전에 먼저 알아두어야 할 것같기에 올립니다.		ASP.NET 책을 준비하다보니 이 정도의 내용은 책에 쓰기 보다 강좌로 올려서 많은 분들이 보실 수 있게 하는 게 바람직해서..		늦었지만... 이제야 올립니다 ^^            </p><p>            </p><hr align="left" color="silver" size="1" width="100%">            		      	<p>강좌 시작 &gt;</p><p>내장 프로시져는 복잡한 SQL 문을 단순화 시켜주고, 보안적인 문제도 해결해 주는 역할을 하며, 매우 빠른 성능을 자랑한다.이는 복잡한 쿼리들을 모아서 하나의 프로시져로 처리할 수 있으며, 그에 따른 처리결과를 돌려주는 형식을 취한다. </p><p>요즘 들어 많은 ASP 문서들에서 스토어드 프로시져의 사용을 권유하고 있다.(물론, 예전부터 그래오기는 했다) 그렇다면, 그토록스토어드 프로시져의 사용을 권유하는 이유는 무엇일까? 이를 사용할 경우 어떠한 장점이 있기에 이를 사용하라고 그토록 이야기하는것일까? 그 중요한 이유 중에 하나는 속도이다. 웹을 다루는 우리에게 언제나 의식할 수 밖에 없는 것이 속도라는 것은 두말할필요가 없을 것이다. 웹 사이트가 갈수록 느려지는 이유 중에 하나는(하드웨어적으로는 문제가 없다고 가정했을 때) 사이트에 많은데이터가 축적되어짐에 따라, 그 데이터를 처리하는 데에 드는 시간이 늘어나기 때문이다. 물론, 갈수록 많은 사용자들이 그러한데이터의 처리를 요구하기 때문이기도 하고 말이다. 어쨋든 갈수록 방대해지는 데이터를 처리하는 데에 드는 속도는 갈수록 떨어질것이기에, 우리는 이 부분에 민감하게 반응할 수 밖에 없다. 물론, 우리가 부유하다면 최고의 장비를 갖추어서 이 문제를 해결할수도 있겠지만, 대부분의 경우 그럴 수가 없는 현실이다.</p><p>그리고, 개발자로서의 자존심이 그렇게 모든 것을 돈으로 해결하게 놔두지는 못할 것이기에 프로그래밍만으로 성능의향상을 높일 수 있는 방법이 있다면 그 어떠한 시도도 지나쳐서는 안될 것이다. 웹 사이트의 속도 저하 원인중에 가장 큰 이유는데이터의 처리속도의 저하이다. 그렇다면, 데이터의 처리속도를 조금이라도 증가시킬 수 있다면 웹 사이트의 속도도 증가할 것이라는것은 당연하다. 바로 그러한 이유에서도 이 스토어드 프로시져는 필수적으로 사용할만한 방법인 것이다.</p><p>저장 프로시져를 사용할 경우에는 일반 SQL 문을 사용할 경우보다 뛰어난 속도의 향상을 가져올 수 있다. 다음의표는 일반 SQL 문과 저장 프로시져간의 비교이다. 이 비교를 통해 왜 저장 프로시져가 더 빠를 수 있는지 여러분은 느낄 수있을 것이다.</p><p><br />
</p><p><table style="width: 523px; height: 255px;" bgcolor="slategray" cellpadding="5" cellspacing="1">	<tbody><tr bgcolor="white">		<td style="font-family: '굴림','Gulim';" width="70"><font size="2">&nbsp;</font></td>		<td style="font-family: '굴림','Gulim';" width="240"><font size="2">일반 SQL 구문</font></td>		<td style="font-family: '굴림','Gulim';" width="270"><font size="2">저장 프로시저</font></td>	</tr>	<tr bgcolor="white">		<td style="font-family: '굴림','Gulim';"><font size="2">만들 때</font></td>		<td style="font-family: '굴림','Gulim';"><font size="2">			1. 키워드 분리 및  문법 검사(파싱작업)<br />
			2. 각 개체의 이름을 확인<br />
			3. 권한 및 보안의 점검<br />
			4. 옵티마이징 (최적화시킨다)<br />
			5. 컴파일의 실행		</font></td>		<td style="font-family: '굴림','Gulim';"><font size="2">			1. 키워드 분리 및  문법 검사(파싱작업)<br />
			2. 각 개체의 이름을 확인<br />
			3. 권한 및 보안의 점검<br />
			4. 옵티마이징 (최적화시킨다)<br />
			5. 결과를 서버에 저장		</font></td>	</tr>		<tr bgcolor="white">		<td style="font-family: '굴림','Gulim';"><font size="2">처음 실행 시</font></td>		<td style="font-family: '굴림','Gulim';"><font size="2">컴파일된 것을 실행한다.		</font></td>		<td style="font-family: '굴림','Gulim';"><font size="2">컴파일하고, 이를 어떻게 실행할 것인지에 대한 실행계획을 만들어 캐쉬에 저장하고 난 뒤 실행한다.		</font></td>	</tr>		<tr bgcolor="white">		<td style="font-family: '굴림','Gulim';"><font size="2">이후 실행 시</font></td>		<td style="font-family: '굴림','Gulim';"><font size="2">		위의 두 과정을 다시 또 수행		</font></td>		<td style="font-family: '굴림','Gulim';"><font size="2">캐쉬를 확인해서 이미 실행계획이 있다면 그를 사용하며, 캐쉬에 실행계획이 없다면 위의 과정을 수행한다.</font></td>	</tr>	</tbody></table>  </p><p>&nbsp;</p><p>&nbsp;뭐가 차이가 있다는 것인지 이해가 잘 안가는가? 그렇다면 유심히 보지않아서 그럴 것이다. 다시 한번 자세히 살펴보자. 분명한 차이가 있다. 일반 SQL 구문의 경우는 실행할 때마다 언제나파싱작업, 개체,보안확인 작업, 컴파일 작업을 반복하게 된다. 하지만, 스토어드 프로시져는 처음에만 단 한번 그 작업을수행하고, 그에 대한 모든 사항을 캐쉬에 올려놓게 된다. 해서 이후 실행시에는 파싱작업, 개체, 보안확인 작업, 컴파일 작업은필요하지 않은 것이다. </p><p>&nbsp;웹과 같이 수많은 사용자가 같은 쿼리를 수도 없이 요청하는 경우를 생각해 보라. 매번 "파싱작업, 개체,보안확인 작업, 컴파일작업"을 반복하는 것과, 단 한번만 이를 수행하고 이후는 캐쉬에서 가져와서 빠르게 수행하는 것과는 대단한 차이가 생길 것이다.사이트의 규모에 따라 예상치도 않은 성능의 향상을 가져올 수도 있다. </p><p>&nbsp;그 뿐이 아니다. ASP에서 ADO를 통해서 데이터베이스에 명령을 날리는 경우 , 그 명령라인의 길이가 길수록 더 많은 크기의데이터를 서버로 전송해야 하기에 네트웍의 트래픽도 늘어나게 된다. 그 명령문의 길이가 짧으면 짧을수록 트래픽은 줄어들 것이고말이다. "에이.. 몇 글자나 된다고 그래?" 할지 모르겠지만 이것은 그냥 웃으며 넘길 정도의 문제가 아니다. </p><p>글 집필시의 최고 이슈 사이트인 모교사랑(ILoveSchool.co.kr)의 경우 동시 사용자가 5만명에 이르른다고 한다.그렇다면 쿼리문의 한, 두글자의 차이는 5만글자, 10만글자의 차이로 늘어나게 되는 것이다. 이제도 웃을 수 있을까? 스토어드프로시져를 사용하면 이 긴 SQL 구문이 프로시져 내부로 들어가게 되기에 이 트래픽 또한 줄일 수 있다. </p><p><br />
</p><p>&nbsp;이제는 맘에 들 것이며, 마구 사용하고 싶어질 것이다. </p><p>거기다가 다음과 같은 추가적인 이익도 있으니 이마저 듣고나면 스토어드 프로시져를 사용하지 않고는 못 배길 것이다. 그것은 바로보안적인 잇점이다. 이제는 익숙해져버린 ASP Security Hole을 여러분은 알고 계실 것이다. 일명 백도어라고 불리우는ASP 소스를 훔쳐볼 수 있는 방법말이다. 만일, 여러분이 ASP 페이지에서 일반 SQL 구문을 사용하여 페이지를 구성하였다면,이 백도어가 오픈될 경우 이 쿼리는 모두 노출될 수 있을 것이다. 하지만, 스토어드 프로시져를 사용한다면 모든 SQL 문은프로시져 내부로 숨어있기에, 단지 프로시져의 이름만이 노출될 뿐, 안심설계일 수 있는 것이다.</p><p>그렇다. 저장 프로시져의 사용은 여러모로 우리에게 유용하다. 그렇다면, 이런 기분좋은 느낌으로 이를 공부해보도록하자. SQL 서버 BOOKS ONLINE(SQL 설치하면 같이 설치되는 도움말) 이나 SQL 서버책에서 이 스토어드 프로시져를만드는 구문을 살펴보면 다음과 같을 것이다.</p><p><table bgcolor="slategray" cellpadding="5" cellspacing="1" width="500">	<tbody><tr bgcolor="#eeeeee">		<td style="padding-left: 30px;"><font size="2"><span style="font-family: '굴림','Gulim';">			CREATE PROC[EDURE] procedure_name [;number]</span><br style="font-family: '굴림','Gulim';"><span style="font-family: '굴림','Gulim';">			&nbsp;&nbsp;&nbsp;&nbsp;[</span><br style="font-family: '굴림','Gulim';"><span style="font-family: '굴림','Gulim';">			&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{@parameter data_type} [VARYING] [= default] [OUTPUT]</span><br style="font-family: '굴림','Gulim';"><span style="font-family: '굴림','Gulim';">			&nbsp;&nbsp;&nbsp;&nbsp;]</span><br style="font-family: '굴림','Gulim';"><span style="font-family: '굴림','Gulim';">			&nbsp;&nbsp;&nbsp;&nbsp;[,...n]</span><br style="font-family: '굴림','Gulim';"><span style="font-family: '굴림','Gulim';">			[WITH </span><br style="font-family: '굴림','Gulim';"><span style="font-family: '굴림','Gulim';">			&nbsp;&nbsp;&nbsp;&nbsp;{</span><br style="font-family: '굴림','Gulim';"><span style="font-family: '굴림','Gulim';">			&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;RECOMPILE </span><br style="font-family: '굴림','Gulim';"><span style="font-family: '굴림','Gulim';">			&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| ENCRYPTION </span><br style="font-family: '굴림','Gulim';"><span style="font-family: '굴림','Gulim';">			&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| RECOMPILE, ENCRYPTION</span><br style="font-family: '굴림','Gulim';"><span style="font-family: '굴림','Gulim';">			&nbsp;&nbsp;&nbsp;&nbsp;}</span><br style="font-family: '굴림','Gulim';"><span style="font-family: '굴림','Gulim';">			]</span><br style="font-family: '굴림','Gulim';"><span style="font-family: '굴림','Gulim';">			[FOR REPLICATION]</span><br style="font-family: '굴림','Gulim';"><span style="font-family: '굴림','Gulim';">			AS</span><br style="font-family: '굴림','Gulim';"><span style="font-family: '굴림','Gulim';">			&nbsp;&nbsp;&nbsp;&nbsp;sql_statement [...n]</span></font><br />
		</td>	</tr></tbody></table></p><p>오오... 대단히 어려워 보인다. 데이터베이스를 전문으로 하지 않는 한, 각각의 인자들이 어디에 어떻게 쓰이는지모두 기억하고 있기는 어려울 것이다. 이 구문에 대한 자세한 사항은 안타깝게도 여기서 모두 다룰 수는 없다. 이 책은 ASP책이며, 그 본분을 다하고 싶기 때문이다. 더욱 자세한 사항은 SQL 서버 책을 살펴보셔야 할 것이다.(BOOKS ONLINE도좋다) 그렇기에 더욱 자세한 부분들에 대해서는 여러분이 차후 시간이 날 경우에 스스로 학습법을 통해서 습득하시기를 바라며,우리는 이 책에서 필요한 정도의 수준만을 같이 해 보려 한다. (좀 더 중급 개발자가 되기 위해서는 SQL 서버는 아니더라도또한, 아주 깊이 있게는 아니더라도 반드시 한 개이상의 데이터베이스를 다룰 수가 있어야 할 것이다. 알고보면 우리도 언제나노력해야 하는 고된 직업을 가지고 있다. )</p><p>일단, 위의 구문을 따르는 가장 간단한 예문을 보면 다음과 같다.</p><p>CREATE  PROC  usp_UpdatePrice_Titles<br />
AS<br />
&nbsp;&nbsp;&nbsp;&nbsp;Update titles SET price = price * 1.2</p><p>이렇게 바라보니 어렵지 않다. 가장 간단한 구문의 스토어드 프로시져는 다음과 같은 구성을 지니게 된다. </p><p>CREATE  PROC(혹은 PROCEDURE)  프로시져 이름<br />
AS<br />
&nbsp;&nbsp;&nbsp;&nbsp;수행할 SQL 쿼리문장</p><p>오오, 이제는 이해하고 싶어지려 한다. 뭐든지 쉬운 것부터 접근해 나가는 것을 필자는 좋아한다. 처음부터 너무어렵게 시작하면 뭐든지 하기가 싫어지는 법이니 말이다. 왠지 초보취급을 하듯이 이야기하는 것 같다고 느낀다면, 필자가 처음에스토어드 프로시져를 알기 위해서 꽤나 어렵게 공부했기에. 그렇기에 여러분에게는 쉽게 풀어주기 위해서 노력하고자 하는 것이니양해해 주길 바라며, 이미 기본지식을 가지고 있는 사람은 적당히 자신에게 맞는 부분으로 속독하며 보아나가면 될 것 같다.</p><p>쿼리 분석기(Query Analyzer)를 열고 다음과 같은 구문을 입력해보도록 한다. </p><p>  <table style="width: 554px; height: 380px;" bgcolor="slategray" cellpadding="10" cellspacing="1">	<tbody><tr bgcolor="white">		<td>		<font color="green" size="2">-- pubs를 사용한다고 설정</font><font size="2"><br />
		Use pubs   <br />
<br />
</font>		<font color="green" size="2">-- 가장 비싼 책의 가격을 확인</font><font size="2"><br />
		Select max(price) from titles  <br />
		GO<br />
<br />
</font>		<font color="green" size="2">-- 프로시저 생성</font><font size="2"><br />
		CREATE  PROC  usp_UpdatePrice_Titles<br />
		AS<br />
		   Update titles SET price = price * 1.2<br />
		GO<br />
<br />
</font>		<font color="green" size="2">-- 만들어진 프로시저를 실행</font><font size="2"><br />
		Exec usp_UpdatePrice_Titles<br />
		GO<br />
<br />
</font>		<font color="green" size="2">-- 가장 비싼 책의 가격을 확인</font><font size="2"><br />
		Select max(price) from titles		</font></td>		<td align="center">						<img src="http://taeyo.pe.kr/lecture/10_ADO/images/sp001.gif" height="358" width="300">						</td>	</tr></tbody></table></p><p> 먼저 위에서 사용한 SQL 문들을 살펴보도록 하자. 먼저 Select max(price) from titles 를통해서 현재 책 가격중에 가장 비싼 책의 가격을 먼저 알아보도록 한다. 그래야, 책의 가격을 변동시킨 뒤, 제대로 변경되었는지확인이 가능할테니 말이다. 그 다음에 Go 라고 되어져 있는 것은 SQL 서버에서 쿼리를 수행할 경우, 각각의 배치를 구분하기위해서 사용한 것이다. 스토어드 프로시져를 만드는 작업이전에는 어떠한 명령도 이전에 존재하지 않아야 하기에 Go를 두어 이전의작업을 먼저 끝내게 한 것이다.</p><p>그리고 난 뒤, 저장 프로시져를 만든다. 이 프로시져의 이름은 usp_UpdatePrice_Titles 이며,이름은 여러분이 원하는대로 주어도 무관하다. 그리고, 이 프로시져는 Update titles SET price = price *1.2 란 쿼리를 수행하도록 만든 것을 볼 수가 있을 것이다. 이 프로시져가 만들어지면 이후로는 Update titles SETprice = price * 1.2 대신에 usp_UpdatePrice_Titles를 실행시켜도 같은 결과를 볼 수가 있을것이다.</p><p>이제 프로시져는 만들어 졌다. 그렇다면, 이 만들어진 프로시져를 실행해보도록 하자. 사용자가 만든 저장 프로시져를실행하기 위해서는 EXEC 라는 명령을 사용하면 된다. 해서 소스에서는 EXEC usp_UpdatePrice_Titles를사용하여 우리가 만든 프로시져를 수행하도록 하고 있다. </p><p>그리고, 다시 가장 비싼 책의 가격을 알아보니 20% 인상이 되어져 있는 것을 알 수가 있다. 이것은 위의 쿼리가 수행되면서 나타나는 결과화면으로 원래의 가격과 인상된 가격의 모습을 볼 수가 있다.</p><p>--------------------- <br />
22.9500<br />
Warning: Null value eliminated from aggregate.  </p><p>                    --------------------- <br />
27.5400<br />
Warning: Null value eliminated from aggregate.</p><p>결과중에 있는 경고는 책값중에 값이 NULL 인 것이 있어서 나는 경고이니 심각하게 받아들이지 않아도 된다. 일반적인 SQL구문을 스토어드 프로시져로 바꾸는 것은 그리 어렵지 않았다. 간단하게만 사용한다면 저장 프로시져도 그렇게 어렵지는 않다.</p><p>이번에는 이 저장 프로시져에 인자를 넘기는 예를 한번 해보도록 하자. 우리 회사에서 갑작스러운 이유로 특정 타입의책들에 대해서는 수시로 가격을 조금은 올리는 경우가 잦다고 가정을 해 보자. 물론, 실제상황에서 그런 일은 없을테지만 단지 예에불과하니까 "예"하고 같이 해보자.</p><p>위와 같은 상황이라면 어떤 쿼리문이 필요할까? 다음과 같은 쿼리문이 필요할 것이다.</p><p>   Update titles SET price = price + 올릴가격<br />
   Where type = 올릴가격의 책 타입</p><p>그렇다면, 이번에는 이것을 프로시져로 만들어 보도록 하자. 그렇다면 이 프로시져로는 두 개의 인자를 넘길 수 있어야할 것이다. 올릴 가격에 대한 값과, 값을 올릴 책의 타입을 말이다. 그런 경우에는 프로시져를 어떻게 제작해야 하는가? 다음처럼하면 된다.</p><p><table bgcolor="slategray" cellpadding="10" cellspacing="1" width="500">	<tbody><tr bgcolor="white">		<td style="padding-left: 40px;"><font size="2">		CREATE  PROC  usp_UpdatePrice2_Titles  <br />
		&nbsp;&nbsp;&nbsp;&nbsp;@type	char(12),<br />
		&nbsp;&nbsp;&nbsp;&nbsp;@plus	int<br />
		AS&gt;<br />
		&nbsp;&nbsp;&nbsp;&nbsp;Update titles SET price = price + @plus<br />
		&nbsp;&nbsp;&nbsp;&nbsp;Where type = @type</font><br />
		</td>	</tr></tbody></table></p><p> 프로시져에서 사용하는 변수는 @하나로 시작한다. 위의 소스에서 보면 프로시져 이름 뒤로, 프로시져 내부의 SQL문에서 필요한 두가지의 인자를 넘기도록 하는 것을 볼 수가 있다. 변수이름은 여러분이 원하는 대로 줄 수 있지만, 그 변수의타입은 잘 맞추어 주어야 한다. 우선 첫 번째 인자로는 책의 타입을 넘겨줄 것이기에 변수 이름을 @type 그 데이터타입은char(12)으로 준 것을 볼 수있다. 그 다음 인자로는 , 를 구분자로 하여 @plus 라는 지정하고 있는데, 이는 책의인상가격이 될 것이다. 데이터 타입은 int 이고 말이다. 이렇게 프로시져 뒤로 두 개의 변수를 받아들이게 되면, 프로시져내에서는 이 값을 가지고 처리를 할 수 있게 된다.</p><p>   이번 프로시져에서는 이 넘어온 두 개의 변수를 사용해서 특정 타입의 책 가격을 특정 값만큼 인상하고 있다. 어렵지 않은 편이다. 그럼 실제로 한번 이 프로시져를 만들어 보자.</p><p> Query Anayzer 에다 위의 프로시져 구문을 입력하고 실행해 보자. 오타 없이 잘 수행했다면 여러분은The command(s) completed successfully.란 메시지를 받을 것이다. 이제 이 프로시져는 만들어 졌다.그렇다면, 이제 이 프로시져를 사용해 보도록 하자. 우리는 책중에서 Business 타입인 책들의 가격을 10 달러 인상시킬계획이다. 그렇게 한번 해보자. </p><p>   	이 프로시져를 사용하기 전에 확인차원에서 현재 titles 테이블의 Business 타입의 책중에 가장 비싼 책의 값이 얼마인지 미리 확인해 두도록 하자. 다음 쿼리를 통해서 말이다.</p><p>   Select max(price) from titles  Where type = 'business'</p><p>   위에서부터 주욱 따라하셨다면 이 값은 23.988 라고 나올 것이다. 이 값을 기억해 두자. 23.988 이 아니라면 그래도 좋다. 하지만, 그럴 경우 그 값을 어딘가에 적어두도록 하자.</p><p>   이제 다음처럼 프로시져를 사용해 보도록 하자.</p><p>   Exec usp_UpdatePrice2_Titles  'business', 10</p><p> 주의할 것은 우리가 프로시져를 만들 때, 첫 번째 인자가 char인 타입 컬럼, 두 번째 인자가 인상할 가격인plus 이었으므로 그 순서에 맞추어 값을 넣어주어야 한다는 사실이다. 만일, 그 순서와 무관하게 가격을 넣고 싶다면, 다음처럼그 변수이름을 사용해서 값을 넣을 수도 있다.</p><p>   Exec usp_UpdatePrice2_Titles  @plus=10, @type=business</p><p>   프로시져를 수행했다면 Select 쿼리를 통해서 가격이 10 달러 증가했는지 확인해 보도록 하자. (필자의 경우라면 가격은 33.988이 되어져 있다.)</p>				      <!--강좌 끝-->            			</td>	</tr></tbody></table>	</td></tr></tbody></table>	<br />
<br />
<table cellspacing="0" width="625"><tbody><tr height="25"><td style="border-right: 1px solid buttonface; border-bottom: 1px solid buttonface; padding-right: 20px; padding-left: 20px;" bgcolor="white"><br />
</td></tr><tr><td style="border-right: 1px solid buttonface; border-bottom: 1px solid buttonface; padding: 20px;"><br />
</td></tr><tr><td style="border-right: 1px solid rgb(203, 203, 203); padding-left: 20px;"><table border="0" width="585"><tbody><tr><td style="padding-bottom: 20px; padding-top: 20px;" valign="top"><br />
<p>이전 강좌에 이어서, 프로시져에 관해서는 이 외에도 OUTPUT을 받아내는 방법과 Return 값을 받아내는 방법등이 존재한다.이들은 각각 프로시져에 인자값을 전달하는 것뿐 아니라, 어떤 결과나 리턴값을 받아낼 수도 있도록 하는 방법이다. 이번에는 이들방법에 대해서 알아볼 차례이다. 그렇다면, 먼저 OUTPUT를 사용하는 방법에 대해서 알아보도록 하자. 쿼리 애널라이저에서다음과 같은 프로시져를 만들어 보자. 굵은 부분이 이번 프로시져에 추가가 된 부분이니 유심히 바라보기 바란다.</p><p><table bgcolor="slategray" cellpadding="5" cellspacing="1" width="500">	<tbody><tr bgcolor="#eeeeee">		<td style="padding-left: 30px;">			<p>CREATE                   PROC usp_UpdatePrice_Output <br />
                  &nbsp;&nbsp;&nbsp;&nbsp;@type&nbsp;&nbsp;&nbsp;&nbsp;char(12), <br />
                  &nbsp;&nbsp;&nbsp;&nbsp;@plus&nbsp;&nbsp;&nbsp;&nbsp;Float, <br />
                  &nbsp;&nbsp;&nbsp;&nbsp;@MaxPrice&nbsp;&nbsp;&nbsp;&nbsp;Float OUTPUT<br />
                   AS<br />
                  Begin <br />
                  &nbsp;&nbsp;&nbsp;&nbsp;Update titles SET price = price + @plus<br />
                  &nbsp;&nbsp;&nbsp;&nbsp;Where type = @type<br />
				  <br />
				  &nbsp;&nbsp;&nbsp;&nbsp;Select @MaxPrice = max(price) from titles Where type = @type<br />
			End</p>		</td>	</tr></tbody></table></p><p>OUTPUT 라는 것은 저장 프로시져에게 인자값을 전달하는 것만이 아니라 되돌려 받을 수도 있게하는 키워드이다.위의 스토어드 프로시져를 보면 알겠지만, 위의 내용은 지정한 타입의 책의 가격을 지정한 만큼 인상한 후, 그 인상한 책중에서가장 비싼 책의 값을 매개변수로써 돌려받는 내용을 갖는다.</p><p>돌려받은 값의 변수이름과 변수타입을 지정한 다음,(여기까지는 기존의 입력인자와 같다) 이 변수는 값을 되돌려 받는데에 사용한다는 의미로 OUTPUT 이라는 키워드를 붙여준다. 그렇게 되면, 이 인자를 통해서 우리가 원하는 값을 얻어올 수있게된다. </p><p>소스를 바라보면, 우리는 특정값을 되돌리기 위해서 @MaxPrice라는 변수를 지정했음을 볼 수가 있다. 그리고, 이 변수는Update 문을 진행한 다음 업데이트된 값중에서 가장 큰 값을 저장하게 됨을 볼 수가 있다. 그 문장이 바로 Select@MaxPrice = max(price) from titles Where type = @type 이다.</p><p>이렇게 되면 우리가 지정한 인자값에 따라 프로시져는 동작하며, 그 결과 적용된 책중에서 가장 비싼 책의 가격을@MaxPrice 라는 변수를 통해서 되돌려주게 된다. 그렇다면, 어떻게 그렇게 할 수 있는지 이 프로시져를 실행하는 예를보도록 하자. 다음이 그 예이다.</p><p>Declare @MaximumPrice&nbsp;&nbsp;&nbsp;&nbsp;Float<br />
Set @MaximumPrice = 0<br />
EXEC usp_UpdatePrice_Output 'business', 10 , @MaximumPrice OUTPUT<br />
Select @MaximumPrice</p><p>위의 구문이 바로 그 되돌림이 있는 프로시져를 수행하는 예인데, 조금은 복잡해 보이지만 알고보면 그렇지도 않다.프로시져를 수행하는 것도 프로그램의 일종이기에 자체적인 문법도 있고, 변수를 사용하게 되면 변수의 선언도 필요하다.(SQL서버의이 프로그래밍을 T-SQL이라고 한다) 우리가 이 되돌림이 있는 프로시져를 사용하는 실제적인 구문은 위에서 굵게 처리한 다음구문이다.</p><p>EXEC usp_UpdatePrice_Output 'business', 10 , @MaximumPrice OUTPUT</p><p>하지만, 이 구문에는 @MaximumPrice 라는 변수가 사용되어진다. 그렇기에 변수의 선언과 변수의 초기화가 필요하다. 해서 </p><p>Declare @MaximumPrice&nbsp;&nbsp;&nbsp;&nbsp;Float<br />
Set @MaximumPrice = 0</p><p>이 두 줄이 먼저 선행되어진 것이다. 그리고, 실제 프로시져 실행구문을 구동한다. 그렇게 되면 프로시져는 동작할것이며, 책 중에서 Business 타입인 책들의 가격을 10 달러씩 증가시킬 것이다. 그리고, 이미 우리가 작성한대로 이업데이트된 가격 중에서 가장 비싼 가격을 @MaximumPrice 라는 변수를 통해서 돌려줄 것이다. 이제 우리가 할 일은 그돌려받은 값이 얼마인지 확인하는 일이다. 필자의 경우 프로시져 수행전의 가격은 33.988 이었으며, 수행 후의 가격은43.988 이 되었다.</p><p><table bgcolor="slategray" cellpadding="5" cellspacing="1" width="540">	<tbody><tr bgcolor="#ffffff">		<td style="padding-left: 20px; padding-right: 20px;">			<p>참고 : 프로시져를 삭제하는 방법은?</p>			<p>어쩌면 Delete를 생각했었을지 모르겠다. 하지만, 실은 Drop이다.<br />
			Drop  PROC  usp_UpdatePrice_Output 과 같이 실행하면 프로시져를 없앨 수 있다.</p>		</td>	</tr></tbody></table></p><p>조금은 방법이 복잡해 보이지만, 이것은 T-SQL을 사용할 경우의 테스트 방법이며, ASP에서는 나름대로의 사용방법이 따로 존재한다. </p><p><table bgcolor="slategray" cellpadding="5" cellspacing="1" width="540">	<tbody><tr bgcolor="#ffffff">		<td style="padding-left: 20px; padding-right: 20px;">			<p>T-SQL이란?</p>			<p>MS SQL 서버에서 사용이 가능한 확장형 SQL 로써, SQL 표준을 따르면서 나름대로 자신을 확장시켜 좀더 세세하게 여러 정보를 다룰 수 있게 한 프로그래밍이 가능한 확장된 SQL이라고 볼 수 있다.</p>		</td>	</tr></tbody></table></p><p>사실, 결과를 되돌려 받기 위해서는 OUTPUT를 사용하지 않고, 그냥 Select 문으로 레코드셋 자체를 넘길 수도 있다. 위의 프로시져는 다음과 같이 사용해도 같은 결과를 나타내게 될 것이다.</p><p><table bgcolor="slategray" cellpadding="5" cellspacing="1" width="500">	<tbody><tr bgcolor="#eeeeee">		<td style="padding-left: 30px;">			<p>CREATE  PROC  usp_UpdatePrice_Output<br />
			&nbsp;&nbsp;&nbsp;&nbsp;@type&nbsp;&nbsp;&nbsp;&nbsp;char(12),<br />
			&nbsp;&nbsp;&nbsp;&nbsp;@plus&nbsp;&nbsp;&nbsp;&nbsp;Float,<br />
			AS<br />
			Begin<br />
			&nbsp;&nbsp;&nbsp;&nbsp;Update titles SET price = price + @plus<br />
&nbsp;&nbsp;&nbsp;&nbsp;Where type =  			   @type<br />
			<br />
			&nbsp;&nbsp;&nbsp;&nbsp;Select max(price) from titles Where type = @type<br />
			End</p>		</td>	</tr></tbody></table></p><p>이렇게 되면, OUTPUT 인자없이도 레코드를 반환할 수가 있다. OUTPUT 의 경우는 오직 하나의 값을 리턴할경우 유리하며, 많은 레코드를 리턴하고 싶을 경우는 이 방법을 사용하는 것이 좋다. 사실 OUTPUT을 사용하는 방법은 그리자주 사용되는 방법은 아니다. </p><p><table bgcolor="slategray" cellpadding="5" cellspacing="1" width="540">	<tbody><tr bgcolor="#ffffff">		<td style="padding-left: 20px; padding-right: 20px;">			<p>프로시져내의 Begin 과 End 란 무엇인가?</p>			<p>이는 구문의 실행과 끝을 알리는 역할을 하는 키워드이다. 실행명령이 한줄로 끝나지 않고, 여러 라인에 걸쳐 여러 명령을수행해야하는 경우 그 구역을 모두 수행하라는 의미로 Begin으로 시작하여 End로 맺음하고 있는 것이다. 마치 자바스크립트나C++에서 { }와 같은 의미이다. T-SQL 에서는 그를 Begin과 End 라는 키워드로써 구분하게 하고 있다. 이미언급했듯이 T-SQL도 프로그래밍 언어에 속하기에 이 또한 자신만의 문법을 가지고 있다.</p>		</td>	</tr></tbody></table></p><p>또, 다르게 값을 되돌릴 수 있는 방법으로는 RETURN 방법이 있다. 이는 사실 프로시져를 마치면서 또는, 비정상 종료하면서Return값을 지정해서 이 프로시져를 호출한 클라이언트가 현재 어떻게 종료되었는지등을 판단하게 하기 위한 수단으로 사용되며,처리결과를 간단히 알리는데 사용되어지게 된다. 주의할 것은 리턴 값은 정수만이 가능하다. (주로 1 아니면 0이다.)</p><p>다음은 Return을 사용하는 프로시져의 예이다. 이 프로시져는 business 책 중에 가장 비싼 책의 가격을인상하기 이전에 그 책의 가격이 50 달러 이상이라면 책 값을 더 이상 인상하지 않고 0을 리턴하게 되며, 아직 50달러미만이라면 가격을 인상한 뒤에 1 이라는 값을 리턴하게 될 것이다.</p><p><table bgcolor="slategray" cellpadding="5" cellspacing="1" width="500">	<tbody><tr bgcolor="#eeeeee">		<td style="padding-left: 30px;">			<p>CREATE  PROC  usp_UpdatePrice_Return<br />
			&nbsp;&nbsp;&nbsp;&nbsp;@type&nbsp;&nbsp;&nbsp;&nbsp;char(12),<br />
			&nbsp;&nbsp;&nbsp;&nbsp;@plus&nbsp;&nbsp;&nbsp;&nbsp;Float<br />
			AS<br />
			Begin <br />
			&nbsp;&nbsp;&nbsp;&nbsp;Declare @Check&nbsp;&nbsp;&nbsp;&nbsp;int<br />
			<br />
&nbsp;&nbsp;&nbsp;&nbsp;Select @Check =  			   Max(price) from titles<br />
&nbsp;&nbsp;&nbsp;&nbsp;Where type =  			   @type<br />
			<br />
&nbsp;&nbsp;&nbsp;&nbsp;if 			@Check &lt;  50 <br />
			&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Begin<br />
			&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Update titles SET price = price + @plus<br />
			&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Where type = @type<br />
			<br />
			&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Select @Check = 1<br />
			&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;End<br />
			&nbsp;&nbsp;&nbsp;&nbsp;Else<br />
			&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Select @Check = 0<br />
			<br />
			&nbsp;&nbsp;&nbsp;&nbsp;Return @Check<br />
			End</p>		</td>	</tr></tbody></table></p><p>그러면, 이 구문을 실행해서 결과를 얻어오려면 어떻게 이 구문을 실행해야 할까? </p><p>Declare @rtn&nbsp;&nbsp;&nbsp;&nbsp;int <br />
EXEC @rtn = usp_UpdatePrice_Return 'business', 10<br />
Select @rtn</p><p>이 바로 그것이다. OUTPUT의 경우와 비교했을 때, 약간의 차이가 있다. 구문의 경우는 OUTPUT 의 경우와는달리 돌려받은 값의 변수이름은 지정하지 않는다. 그리고, 실행시에는 리턴값을 받기위해, 프로시져 이름 앞에서 프로시져의 결과를대입하는 모습을 띈 @rtn = usp_UpdatePrice_Return 가 인상적이다. 어려울 것은 없다. OUTPUT 보다는조금은 단순한 모습을 띄고 있으니 말이다. </p><p>지금의 예는 뭔가 현실적이지는 못하지만, 여러분은 여러 가지 모습으로 이러한 Return 값을 가지는 프로시져를 구성할 수 있을것이다. 예를 들면, 회원가입시 현재 등록하고자 하는 사람의 아이디가 이미 존재하는지의 여부를 체크해서 존재한다면 1, 아니라면0을 리턴하여 처리할 수도 있을 것이다.</p><p> 조금은 부족한 듯 하지만, 스토어드 프로시져의 사용법에 대해서 우리는 알아보았다. 이들은 간단하지만 가장기본적인 프로시져의 사용예이니 적어도 이 정도는 이해하고 있어야만 한다. 이미 언급했듯이, 더욱 자세한 스토어드 프로시져에 대한내용은 관련서적을 통해서 얻으셔야 한다. 이 스토어드 프로시져를 작성하는 구문이나 문법에 대해서는 T-SQL 문을 또한, 따로공부하셔야 한다.</p>            <p>여러분의 마음은 필자도 알고 있다. 여기서 T-SQL 문법이나 구문에 대해서도 알려주었으면 한다는 것을 말이다.             하지만, 그것이 그리 쉽지 않은 것이 T-SQL은 그것만으로도 두꺼운 책 한권이다. 역시 그도 하나의 언어이기 때문이다.             해서, 그를 여기서 설명한다는 것은 무리가 있다. 그에 대한 지식은 여러분이 필요한 만큼 SQL 서버 책이나 T-SQL 책             내지는 SQL Books Online을 통해서 얻으셔야만 한다.&nbsp;</p>            <p>이 지식은 여러분이 ASP 에서 ADO Command 개체를&nbsp;사용하고자 할 경우나, ADO.NET의             Command 관련 개체들을 사용할 경우 아주&nbsp;유용한&nbsp;지식이 되어줄&nbsp;것이라 믿어 의심치             않는다.</p>            <p>&nbsp;</p></td></tr></tbody></table></td></tr></tbody></table><br />
			 ]]> 
		</description>
		<category>Task</category>

		<comments>http://namkee.egloos.com/3367643#comments</comments>
		<pubDate>Wed, 02 May 2007 07:09:52 GMT</pubDate>
		<dc:creator>namkee</dc:creator>
	</item>
	<item>
		<title><![CDATA[ org.xml.sax.SAXParseException: An invalid XML character unicode ... ]]> </title>
		<link>http://namkee.egloos.com/3337852</link>
		<guid>http://namkee.egloos.com/3337852</guid>
		<description>
			<![CDATA[ 
  http://e-docs.bea.com/wls/docs81/notes/resolved_sp03.html<br />
<br />
기존의 탐켓에서 작업한 was 를 망할놈의-_- 웹로직(weblogic)에서 돌리려니 골머리가 지근지근..-_-;<br />
<br />
이클립스에서 xml 설정파일을 좀 건드려줬더니 잘돌아가던 놈이 Exception 에러가 난다..<br />
<br />
뭐 대충 이렇다<br />
SAXParseException : An invalid XML character (Unicode: 0x10) was found in the element content of the document.<br />
xml 읽어들이다가 인식안되는 유니코드 발견되었다는 건데.. 레퍼런스 찾아 헤메다가 <br />
<br />
웹로직 만든 bea edoc 에서 친절히 설명해 주신다.<br />
<br />
<p class="table">Previously, it was not possible touse JavaServer Pages Standard Tag Library (JSTL) tags in JSPs thatinclude Japanese characters. When such a JSP is executed, an errorstarting with the following lines occurred:</p><p class="table"><a name="1818642"></a><code style="font-family: courier;">java.io.IOException:javax.servlet.jsp.JspException: The taglib validator rejected the page:"org.xml.sax.SAXParseException: An invalid XML character (Unicode:0x82) was found in the CDATA section."</code></p><p class="table"><a name="1818643"></a>If the <code style="font-family: courier;">pageEncoding</code>attribute was not specified in the page directive, the byte stream,which is used for taglib validation, was constructed using defaultencoding. </p><p class="table"><a name="1818644"></a>The problem was corrected with a code change to ensure use of the character encoding defined in the <code style="font-family: courier;">contentType</code> attribute if the <code style="font-family: courier;">pageEncoding</code> is not specified.</p><br />
<br />
페이지 인코딩의 문제였다. xml 파일이 페이지 인코딩이 euc-kr로 되어있다. 이걸 UTF-8로 바꿀것인가... 아마도 주석 달면서 한글쓰면서 개행문자가 들어간걸 잘못 읽어들이는 문제인듯 하다. <br />
invalid XML character 라면서 나온 유니코드가 개행문자 였으니..<br />
아무튼 문제는 이것으로 일단락!<br />
			 ]]> 
		</description>
		<category>Task</category>

		<comments>http://namkee.egloos.com/3337852#comments</comments>
		<pubDate>Mon, 23 Apr 2007 09:14:13 GMT</pubDate>
		<dc:creator>namkee</dc:creator>
	</item>
	<item>
		<title><![CDATA[ ClassNotFoundException: org.hibernate.hql.ast.HqlToken (WebLogic, Hibernate) ]]> </title>
		<link>http://namkee.egloos.com/3252977</link>
		<guid>http://namkee.egloos.com/3252977</guid>
		<description>
			<![CDATA[ 
  톰캣 환경에서 개발된 Hibernate를 사용하는 Web Application 을 웹로직(WebLogic)으로 배포하여 실행시에 다음과 같은 에러가 발생하였습니다.<br />
<br />
<br />
ClassNotFoundException: org.hibernate.hql.ast.HqlToken<br />
<br />
<br />
Hibernate.org 의 레퍼런스를 참조해보면 <br />
<br />
ClassNotFoundException: org.hibernate.hql.ast.HqlToken - Hibernate 3.x includes a new query parser that doesn't run on Weblogic - the reason is a packaging error of ANTLR in Weblogic's boot classpath<br />
<br />
Hibernate 3.x 에서 이용하는 쿼리 파서(ANTLR parser)가 웹로직에서는 돌아가지 않는것에서 발생하는 에러 입니다. (Hibernate 를 사용한다면 antlr-2.x.xH3.jar 파일이 lib 에 속해 있습니다.)<br />
<br />
계속되는 Hibernate.org의 글은.<br />
<strong>BEA Weblogic issues</strong><br />
<br />
&nbsp;Hibernate3 uses ANTLR for the new query parser. Unfortunately BEA Weblogic includes a version of ANTLR in the system classpath which will be loaded before any application libraries and, because Weblogic doesn't seem to support proper class loader isolation, will not see the Hibernate classes in the application's context.<br />
<br />
&nbsp;BEA seems to solve this issue by prefixing package names, but the distributed ANTLR doesn't have this prefix. Another source for this issue is the usage of Class.forName() in ANTLR itself.<br />
<br />
&nbsp;Until both parties have solved these issues we can only provide workarounds: Place all your Hibernate and dependent libraries on the application server's boot classpath or use the old query parser as described above.<br />
<br />
&nbsp;The Hibernate Team has sent a fix for this issue to the ANTLR developers, and it should be included in the next release. We'll distribute this new version with a minor release of Hibernate in the next few weeks or months. <br />
<br />
&nbsp;For now we distribute a patched version of ANTLR with Hibernate 3.0 which uses the context classloader instead of Class.forName().<br />
<br />
&nbsp;The Weblogic classloading and/or package prefix issues are unfortunately out of our reach. We encourage you to contact your BEA support representative. As per the BEA support team, ANTLR is used in Weblogic for their EJB-QL parser, so if you do not use their CMP engine, you're safe to use the new ANTLR version.<br />
<br />
<br />
<br />
<br />
문제를 해결하기 위해 Hibernate 를 3.1 이상의 버전으로 업그레이드 해주는 방법이 있겠지만 배보다 배꼽이 더클것 같은 두려움에 class path 에 antlr----.jar 파일을 포함시켜주는 것으로 해결하였습니다. <br />
<br />
<br />
antlr-2.7.5H3.jar <br />
webroot/WEB-INF/lib/antlr-2.7.5H3.jar<br />
<br />
<br />
-&gt;myEclipse 에서<br />
&nbsp;: Configure Server 에서 Paths &gt; Prepend to classpath &gt; Add Jar/Zip 에서 추가.<br />
<br />
<br />
<br />
-&gt;startWebLogic.cmd 로 실행시.<br />
&nbsp;: 1. webroot/WEB-INF/lib/antlr-2.7.5H3.jar 을 weblogic81/server/lib/antlr/antlr-2.7.5H3.jar 로 만듬<br />
&nbsp;&nbsp; 2. \mydomain\setDomainEnv.cmd 에서 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; set CLASSPATH 에&nbsp; %ARDIR%\antlr\antlr-2.7.5H3.jar 추가.<br />
&nbsp;&nbsp; 3. 마지막 set CLASSPATH 에 제일 앞으로 옮겨준다.<br />
<br />
&nbsp;			 ]]> 
		</description>
		<category>Task</category>

		<comments>http://namkee.egloos.com/3252977#comments</comments>
		<pubDate>Fri, 30 Mar 2007 04:07:17 GMT</pubDate>
		<dc:creator>namkee</dc:creator>
	</item>
	<item>
		<title><![CDATA[ Jakarta Project: String Tag library Version: 1.1.0 ]]> </title>
		<link>http://namkee.egloos.com/3121949</link>
		<guid>http://namkee.egloos.com/3121949</guid>
		<description>
			<![CDATA[ 
  <center><h1>Jakarta Project: String Tag library</h1></center><center><h3>Version: 1.1.0</h3></center><p align="left"><a href="http://jakarta.apache.org/taglibs/doc/string-doc/">http://jakarta.apache.org/taglibs/doc/string-doc/</a></p><h3>Table of Contents</h3><ul><li><a href="http://jakarta.apache.org/taglibs/doc/string-doc/#overview">Overview</a> <li><a href="http://jakarta.apache.org/taglibs/doc/string-doc/#requirements">Requirements</a> <li><a href="http://jakarta.apache.org/taglibs/doc/string-doc/#config">Configuration</a> <li><a href="http://jakarta.apache.org/taglibs/doc/string-doc/#summary">Tag Summary</a> <li><a href="http://jakarta.apache.org/taglibs/doc/string-doc/#reference">Tag Reference</a> <li><a href="http://jakarta.apache.org/taglibs/doc/string-doc/#examples">Examples</a> <li><a href="http://jakarta.apache.org/taglibs/doc/string-doc/#javadocs">Javadocs</a> <li><a href="http://jakarta.apache.org/taglibs/doc/string-doc/#history">Revision History</a> </li></ul><a name="overview"></a><h3>Overview</h3><p>The String taglibrary provides a host of tags for manipulating java.lang.Strings. The style is that the String to act upon is the body of the tag, and attributes are used as parameters for the manipulation. </p><a name="requirements"></a><h3>Requirements</h3><p>This taglib is currently built on top of the <a href="http://jakarta.apache.org/commons/lang/index.html">Lang 2.0</a> component from <a href="http://jakarta.apache.org/commons/">Jakarta Commons</a>. In addition a servlet container is required that supports the JavaServer Pages Specification, version 1.1 or higher. </p><a name="config"></a><h3>Configuration</h3><p>Follow these steps to configure your web application with this tag library:</p><ul><li>Copy the tag library descriptor file to the /WEB-INF subdirectory of your web application. <li>Copy the tag library JAR file to the /WEB-INF/lib subdirectory of your web application. <li>Add a &lt;taglib&gt; element to your web application deployment descriptor in /WEB-INF/web.xml like this: <pre>&lt;taglib&gt;   &lt;taglib-uri&gt;http://jakarta.apache.org/taglibs/string-1.1&lt;/taglib-uri&gt;   &lt;taglib-location&gt;/WEB-INF/string.tld&lt;/taglib-location&gt; &lt;/taglib&gt; </pre></li></ul><p>To use the tags from this library in your JSP pages, add the following directive at the top of each page: </p><pre>&lt;%@ taglib uri="http://jakarta.apache.org/taglibs/string-1.1" prefix="str" %&gt; </pre><p>where "<i>str</i>" is the tag name prefix you wish to use for tags from this library. You can change this value to any prefix you like.</p><a name="summary"></a><h3>Tag Summary</h3><b>String Tags</b> <table cellspacing="3" cellpadding="3" width="90%" border="0"><tbody><tr><td valign="top" width="25%"><a href="http://jakarta.apache.org/taglibs/doc/string-doc/#length">length</a></td><td width="75%">Return the length of a String. An empty string is returned for a null String if one should somehow be passed in. </td></tr><tr><td valign="top" width="25%"><a href="http://jakarta.apache.org/taglibs/doc/string-doc/#capitalize">capitalize</a></td><td width="75%">Capitalize a String. The first character is converted to TitleCase. </td></tr><tr><td valign="top" width="25%"><a href="http://jakarta.apache.org/taglibs/doc/string-doc/#uncapitalize">uncapitalize</a></td><td width="75%">Change the first letter of a String to Lowercase. </td></tr><tr><td valign="top" width="25%"><a href="http://jakarta.apache.org/taglibs/doc/string-doc/#upperCase">upperCase</a></td><td width="75%">Turn the entire String to uppercase. Delegates to java.lang.String, so no idea if it uses Titlecase when it's supposed to. </td></tr><tr><td valign="top" width="25%"><a href="http://jakarta.apache.org/taglibs/doc/string-doc/#lowerCase">lowerCase</a></td><td width="75%">Turn all uppercase and titlecase characters to lowercase. </td></tr><tr><td valign="top" width="25%"><a href="http://jakarta.apache.org/taglibs/doc/string-doc/#trim">trim</a></td><td width="75%">Remove whitespace from start and end of a String. </td></tr><tr><td valign="top" width="25%"><a href="http://jakarta.apache.org/taglibs/doc/string-doc/#chop">chop</a></td><td width="75%">Remove the last character from a String. If it is a \n and a \r precedes it, then remove that too. </td></tr><tr><td valign="top" width="25%"><a href="http://jakarta.apache.org/taglibs/doc/string-doc/#chopNewline">chopNewline</a></td><td width="75%">Remove a \n from the end of a String if it is there. If a \r precedes it, then it removes that too. </td></tr><tr><td valign="top" width="25%"><a href="http://jakarta.apache.org/taglibs/doc/string-doc/#escape">escape</a></td><td width="75%">Escape a String into a Java-compatible String. Handles unicode, and the standard escapes: \t, \b, \n, \f, \r, \\, \", \' </td></tr><tr><td valign="top" width="25%"><a href="http://jakarta.apache.org/taglibs/doc/string-doc/#reverse">reverse</a></td><td width="75%">Reverse a String. </td></tr><tr><td valign="top" width="25%"><a href="http://jakarta.apache.org/taglibs/doc/string-doc/#swapCase">swapCase</a></td><td width="75%">Swap the casing in a String. Lowercase goes to Uppercase or Titlecase depending on whether they are the first in the String or after whitespace. Uppercase and Titlecase go to Lowercase </td></tr><tr><td valign="top" width="25%"><a href="http://jakarta.apache.org/taglibs/doc/string-doc/#soundex">soundex</a></td><td width="75%">Return the US_ENGLISH Soundex of a String. </td></tr><tr><td valign="top" width="25%"><a href="http://jakarta.apache.org/taglibs/doc/string-doc/#metaphone">metaphone</a></td><td width="75%">Get the metaphone for a String. This is an improved variant of SoundEx. </td></tr><tr><td valign="top" width="25%"><a href="http://jakarta.apache.org/taglibs/doc/string-doc/#quoteRegexp">quoteRegexp</a></td><td width="75%">Quote a String so that it will pass through a regular expression as a constant. </td></tr><tr><td valign="top" width="25%"><a href="http://jakarta.apache.org/taglibs/doc/string-doc/#capitalizeAllWords">capitalizeAllWords</a></td><td width="75%">Capitalize all the words found in a piece of body text. Capitalization is performed upon any letters following whitespace, and on the first character. </td></tr><tr><td valign="top" width="25%"><a href="http://jakarta.apache.org/taglibs/doc/string-doc/#removeXml">removeXml</a></td><td width="75%">Remove any XML tags from a String. A very simple algorithm which just removes any &lt;..&gt; blocks of text. </td></tr><tr><td valign="top" width="25%"><a href="http://jakarta.apache.org/taglibs/doc/string-doc/#encodeUrl">encodeUrl</a></td><td width="75%">Encode a String to that it may be used as a URL. Note: accented characters may not be encoded correctly, but there is not we can do about it (a solution would be passing the encoding as an attribute, but that would require a J2SE 1.4 environment). </td></tr><tr><td valign="top" width="25%"><a href="http://jakarta.apache.org/taglibs/doc/string-doc/#decodeUrl">decodeUrl</a></td><td width="75%">Decode a URL so it may be nicely printed. Note: accented characters may not be encoded correctly, but there is not we can do about it (a solution would be passing the encoding as an attribute, but that would require a J2SE 1.4 environment). </td></tr><tr><td valign="top" width="25%"><a href="http://jakarta.apache.org/taglibs/doc/string-doc/#count">count</a></td><td width="75%">Count the number of occurences of a passed in 'Set'. A Set is a String of a particular format. It may include ranges and single characters. A Set may be negated. range - "a-z" char - "a" negate - "^a" </td></tr><tr><td valign="top" width="25%"><a href="http://jakarta.apache.org/taglibs/doc/string-doc/#delete">delete</a></td><td width="75%">Delete any characters from the body that match characters specified in the Set. The syntax of a Set is described in Count. </td></tr><tr><td valign="top" width="25%"><a href="http://jakarta.apache.org/taglibs/doc/string-doc/#squeeze">squeeze</a></td><td width="75%">Squeeze any characters from the body that match characters specified in the Set. Squeezing means that if it finds two adjoining characters that are the same, they are replaced with a single one of the characters. The syntax of a Set is described in the Count tag. </td></tr><tr><td valign="top" width="25%"><a href="http://jakarta.apache.org/taglibs/doc/string-doc/#center">center</a></td><td width="75%">Center the body String in a larger String of size width. </td></tr><tr><td valign="top" width="25%"><a href="http://jakarta.apache.org/taglibs/doc/string-doc/#rightPad">rightPad</a></td><td width="75%">Right pad a string with a particular delimiter to a specified width. The width includes the size of the string. </td></tr><tr><td valign="top" width="25%"><a href="http://jakarta.apache.org/taglibs/doc/string-doc/#leftPad">leftPad</a></td><td width="75%">Left pad a string with a particular delimiter to a specified width. The width includes the size of the string. </td></tr><tr><td valign="top" width="25%"><a href="http://jakarta.apache.org/taglibs/doc/string-doc/#chomp">chomp</a></td><td width="75%">Remove the last occurence of a specified character, and everything after it. </td></tr><tr><td valign="top" width="25%"><a href="http://jakarta.apache.org/taglibs/doc/string-doc/#getChomp">getChomp</a></td><td width="75%">Get everything after a specified delimiter. Returns the delimiter as well. </td></tr><tr><td valign="top" width="25%"><a href="http://jakarta.apache.org/taglibs/doc/string-doc/#prechomp">prechomp</a></td><td width="75%">Remove everything up until a specified delimiter, and that specified delimiter from the start of a String. </td></tr><tr><td valign="top" width="25%"><a href="http://jakarta.apache.org/taglibs/doc/string-doc/#getPrechomp">getPrechomp</a></td><td width="75%">Get everything up until a specific delimiter. Returns the delimiter as well. </td></tr><tr><td valign="top" width="25%"><a href="http://jakarta.apache.org/taglibs/doc/string-doc/#strip">strip</a></td><td width="75%">Strip all of a specified character which appear at the start and end of a String. </td></tr><tr><td valign="top" width="25%"><a href="http://jakarta.apache.org/taglibs/doc/string-doc/#stripEnd">stripEnd</a></td><td width="75%">Strip all of a specified character which appear at the end of a String. </td></tr><tr><td valign="top" width="25%"><a href="http://jakarta.apache.org/taglibs/doc/string-doc/#stripStart">stripStart</a></td><td width="75%">Strip all of a specified character which appear at the start of a String. </td></tr><tr><td valign="top" width="25%"><a href="http://jakarta.apache.org/taglibs/doc/string-doc/#reverseDelimitedString">reverseDelimitedString</a></td><td width="75%">Reverses a delimited String. One example would be changing org.apache.taglib to taglib.apache.org. The delimiter to use is settable. </td></tr><tr><td valign="top" width="25%"><a href="http://jakarta.apache.org/taglibs/doc/string-doc/#overlay">overlay</a></td><td width="75%">Overlay a String on top of another String. The length of the String to overlay does not have to be the same as the size of substring it replaces. </td></tr><tr><td valign="top" width="25%"><a href="http://jakarta.apache.org/taglibs/doc/string-doc/#substring">substring</a></td><td width="75%">Get a specified substring from a larger String based on the start index and end-before index in the larger String </td></tr><tr><td valign="top" width="25%"><a href="http://jakarta.apache.org/taglibs/doc/string-doc/#repeat">repeat</a></td><td width="75%">Repeat a string a particular number of times. </td></tr><tr><td valign="top" width="25%"><a href="http://jakarta.apache.org/taglibs/doc/string-doc/#wordWrap">wordWrap</a></td><td width="75%">Word-wrap a String. This involves formatting a long String to fit within a certain character width of page. A delimiter may be passed in to put at the end of each line and a splitting character can be specified for when a word has to be cut in half. </td></tr><tr><td valign="top" width="25%"><a href="http://jakarta.apache.org/taglibs/doc/string-doc/#nestedString">nestedString</a></td><td width="75%">Get a String that is nested between an open and closing substring. </td></tr><tr><td valign="top" width="25%"><a href="http://jakarta.apache.org/taglibs/doc/string-doc/#countMatches">countMatches</a></td><td width="75%">Return the number of times that the body String contains the sub-string. </td></tr><tr><td valign="top" width="25%"><a href="http://jakarta.apache.org/taglibs/doc/string-doc/#default">default</a></td><td width="75%">If the body String is a particular value, then output a default value, else output the body String. The major use of this is to convert 'null' into an empty String. </td></tr><tr><td valign="top" width="25%"><a href="http://jakarta.apache.org/taglibs/doc/string-doc/#replace">replace</a></td><td width="75%">Replace a specified substring with another string. A number of times may be specified to say how many times to replace the substring. </td></tr><tr><td valign="top" width="25%"><a href="http://jakarta.apache.org/taglibs/doc/string-doc/#randomString">randomString</a></td><td width="75%">Create a random string. It can create an ascii string, a numeric string, an alphanumeric string, and a unicode string. The size of the string may be specified, as can a start and end character. Lastly, a set of characters to use may be passed in. </td></tr><tr><td valign="top" width="25%"><a href="http://jakarta.apache.org/taglibs/doc/string-doc/#left">left</a></td><td width="75%">Get the leftmost 'n' characters from a string. </td></tr><tr><td valign="top" width="25%"><a href="http://jakarta.apache.org/taglibs/doc/string-doc/#right">right</a></td><td width="75%">Get the rightmost 'n' characters from a string. </td></tr><tr><td valign="top" width="25%"><a href="http://jakarta.apache.org/taglibs/doc/string-doc/#mid">mid</a></td><td width="75%">Get 'n' characters from the inside of a string. The start position may be set, or the default may be used. The default is to get the central characters. </td></tr><tr><td valign="top" width="25%"><a href="http://jakarta.apache.org/taglibs/doc/string-doc/#truncateNicely">truncateNicely</a></td><td width="75%">A more intelligent substring. It attempts to cut off a string after a space, following predefined or user-supplied lower and upper limits, useful for making short descriptions from long text. It strips the HTML out as a part of the code. Patches on a version which doesn't strip the HTML will be gratefully received. </td></tr><tr><td valign="top" width="25%"><a href="http://jakarta.apache.org/taglibs/doc/string-doc/#join">join</a></td><td width="75%">Joins the elements of the provided array. </td></tr><tr><td valign="top" width="25%"><a href="http://jakarta.apache.org/taglibs/doc/string-doc/#split">split</a></td><td width="75%">Splits the provided text into an array, separators specified. The separator is not included in the returned String array and adjacent separators are treated as one separator. </td></tr><tr><td colspan="2">&nbsp;</td></tr></tbody></table><a name="reference"></a><h3>Tag Reference</h3><table cellspacing="3" cellpadding="3" width="90%" border="0"><tbody><tr bgcolor="#cccccc"><td colspan="5"><b><font size="+1"><a name="length">length</a></font></b></td><td align="right" width="17%">Availability:&nbsp;1.2</td></tr><tr><td colspan="6"><p>Return the length of a String. An empty string is returned for a null String if one should somehow be passed in. </p></td></tr><tr><td width="15%"><b>Tag Body</b></td><td width="17%">JSP</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td></tr><tr><td><b>Restrictions</b></td><td colspan="5"><p>None</p></td></tr><tr><td><b>Attributes</b></td><td>Name</td><td>Required</td><td colspan="2">Runtime&nbsp;Expression&nbsp;Evaluation </td><td>Availability</td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>var</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.2</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Variable to store result in. </p></td></tr><tr><td><b>Variables</b></td><td colspan="5">None</td></tr><tr><td><b>Examples</b></td><td colspan="5">None</td></tr></tbody></table><table cellspacing="3" cellpadding="3" width="90%" border="0"><tbody><tr bgcolor="#cccccc"><td colspan="5"><b><font size="+1"><a name="capitalize">capitalize</a></font></b></td><td align="right" width="17%">Availability:&nbsp;1.0</td></tr><tr><td colspan="6"><p>Capitalize a String. The first character is converted to TitleCase. </p></td></tr><tr><td width="15%"><b>Tag Body</b></td><td width="17%">JSP</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td></tr><tr><td><b>Restrictions</b></td><td colspan="5"><p>None</p></td></tr><tr><td><b>Attributes</b></td><td>Name</td><td>Required</td><td colspan="2">Runtime&nbsp;Expression&nbsp;Evaluation </td><td>Availability</td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>var</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Variable to store result in. </p></td></tr><tr><td><b>Variables</b></td><td colspan="5">None</td></tr><tr><td><b>Examples</b></td><td colspan="5">None</td></tr></tbody></table><table cellspacing="3" cellpadding="3" width="90%" border="0"><tbody><tr bgcolor="#cccccc"><td colspan="5"><b><font size="+1"><a name="uncapitalize">uncapitalize</a></font></b></td><td align="right" width="17%">Availability:&nbsp;1.0</td></tr><tr><td colspan="6"><p>Change the first letter of a String to Lowercase. </p></td></tr><tr><td width="15%"><b>Tag Body</b></td><td width="17%">JSP</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td></tr><tr><td><b>Restrictions</b></td><td colspan="5"><p>None</p></td></tr><tr><td><b>Attributes</b></td><td>Name</td><td>Required</td><td colspan="2">Runtime&nbsp;Expression&nbsp;Evaluation </td><td>Availability</td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>var</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Variable to store result in. </p></td></tr><tr><td><b>Variables</b></td><td colspan="5">None</td></tr><tr><td><b>Examples</b></td><td colspan="5">None</td></tr></tbody></table><table cellspacing="3" cellpadding="3" width="90%" border="0"><tbody><tr bgcolor="#cccccc"><td colspan="5"><b><font size="+1"><a name="upperCase">upperCase</a></font></b></td><td align="right" width="17%">Availability:&nbsp;1.0</td></tr><tr><td colspan="6"><p>Turn the entire String to uppercase. Delegates to java.lang.String, so no idea if it uses Titlecase when it's supposed to. </p></td></tr><tr><td width="15%"><b>Tag Body</b></td><td width="17%">JSP</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td></tr><tr><td><b>Restrictions</b></td><td colspan="5"><p>None</p></td></tr><tr><td><b>Attributes</b></td><td>Name</td><td>Required</td><td colspan="2">Runtime&nbsp;Expression&nbsp;Evaluation </td><td>Availability</td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>var</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Variable to store result in. </p></td></tr><tr><td><b>Variables</b></td><td colspan="5">None</td></tr><tr><td><b>Examples</b></td><td colspan="5">None</td></tr></tbody></table><table cellspacing="3" cellpadding="3" width="90%" border="0"><tbody><tr bgcolor="#cccccc"><td colspan="5"><b><font size="+1"><a name="lowerCase">lowerCase</a></font></b></td><td align="right" width="17%">Availability:&nbsp;1.0</td></tr><tr><td colspan="6"><p>Turn all uppercase and titlecase characters to lowercase. </p></td></tr><tr><td width="15%"><b>Tag Body</b></td><td width="17%">JSP</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td></tr><tr><td><b>Restrictions</b></td><td colspan="5"><p>None</p></td></tr><tr><td><b>Attributes</b></td><td>Name</td><td>Required</td><td colspan="2">Runtime&nbsp;Expression&nbsp;Evaluation </td><td>Availability</td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>var</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Variable to store result in. </p></td></tr><tr><td><b>Variables</b></td><td colspan="5">None</td></tr><tr><td><b>Examples</b></td><td colspan="5">None</td></tr></tbody></table><table cellspacing="3" cellpadding="3" width="90%" border="0"><tbody><tr bgcolor="#cccccc"><td colspan="5"><b><font size="+1"><a name="trim">trim</a></font></b></td><td align="right" width="17%">Availability:&nbsp;1.0</td></tr><tr><td colspan="6"><p>Remove whitespace from start and end of a String. </p></td></tr><tr><td width="15%"><b>Tag Body</b></td><td width="17%">JSP</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td></tr><tr><td><b>Restrictions</b></td><td colspan="5"><p>None</p></td></tr><tr><td><b>Attributes</b></td><td>Name</td><td>Required</td><td colspan="2">Runtime&nbsp;Expression&nbsp;Evaluation </td><td>Availability</td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>var</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Variable to store result in. </p></td></tr><tr><td><b>Variables</b></td><td colspan="5">None</td></tr><tr><td><b>Examples</b></td><td colspan="5">None</td></tr></tbody></table><table cellspacing="3" cellpadding="3" width="90%" border="0"><tbody><tr bgcolor="#cccccc"><td colspan="5"><b><font size="+1"><a name="chop">chop</a></font></b></td><td align="right" width="17%">Availability:&nbsp;1.0</td></tr><tr><td colspan="6"><p>Remove the last character from a String. If it is a \n and a \r precedes it, then remove that too. </p></td></tr><tr><td width="15%"><b>Tag Body</b></td><td width="17%">JSP</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td></tr><tr><td><b>Restrictions</b></td><td colspan="5"><p>None</p></td></tr><tr><td><b>Attributes</b></td><td>Name</td><td>Required</td><td colspan="2">Runtime&nbsp;Expression&nbsp;Evaluation </td><td>Availability</td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>var</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Variable to store result in. </p></td></tr><tr><td><b>Variables</b></td><td colspan="5">None</td></tr><tr><td><b>Examples</b></td><td colspan="5">None</td></tr></tbody></table><table cellspacing="3" cellpadding="3" width="90%" border="0"><tbody><tr bgcolor="#cccccc"><td colspan="5"><b><font size="+1"><a name="chopNewline">chopNewline</a></font></b></td><td align="right" width="17%">Availability:&nbsp;1.0</td></tr><tr><td colspan="6"><p>Remove a \n from the end of a String if it is there. If a \r precedes it, then it removes that too. </p></td></tr><tr><td width="15%"><b>Tag Body</b></td><td width="17%">JSP</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td></tr><tr><td><b>Restrictions</b></td><td colspan="5"><p>None</p></td></tr><tr><td><b>Attributes</b></td><td>Name</td><td>Required</td><td colspan="2">Runtime&nbsp;Expression&nbsp;Evaluation </td><td>Availability</td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>var</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Variable to store result in. </p></td></tr><tr><td><b>Variables</b></td><td colspan="5">None</td></tr><tr><td><b>Examples</b></td><td colspan="5">None</td></tr></tbody></table><table cellspacing="3" cellpadding="3" width="90%" border="0"><tbody><tr bgcolor="#cccccc"><td colspan="5"><b><font size="+1"><a name="escape">escape</a></font></b></td><td align="right" width="17%">Availability:&nbsp;1.0</td></tr><tr><td colspan="6"><p>Escape a String into a Java-compatible String. Handles unicode, and the standard escapes: \t, \b, \n, \f, \r, \\, \", \' </p></td></tr><tr><td width="15%"><b>Tag Body</b></td><td width="17%">JSP</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td></tr><tr><td><b>Restrictions</b></td><td colspan="5"><p>None</p></td></tr><tr><td><b>Attributes</b></td><td>Name</td><td>Required</td><td colspan="2">Runtime&nbsp;Expression&nbsp;Evaluation </td><td>Availability</td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>var</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Variable to store result in. </p></td></tr><tr><td><b>Variables</b></td><td colspan="5">None</td></tr><tr><td><b>Examples</b></td><td colspan="5">None</td></tr></tbody></table><table cellspacing="3" cellpadding="3" width="90%" border="0"><tbody><tr bgcolor="#cccccc"><td colspan="5"><b><font size="+1"><a name="reverse">reverse</a></font></b></td><td align="right" width="17%">Availability:&nbsp;1.0</td></tr><tr><td colspan="6"><p>Reverse a String. </p></td></tr><tr><td width="15%"><b>Tag Body</b></td><td width="17%">JSP</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td></tr><tr><td><b>Restrictions</b></td><td colspan="5"><p>None</p></td></tr><tr><td><b>Attributes</b></td><td>Name</td><td>Required</td><td colspan="2">Runtime&nbsp;Expression&nbsp;Evaluation </td><td>Availability</td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>var</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Variable to store result in. </p></td></tr><tr><td><b>Variables</b></td><td colspan="5">None</td></tr><tr><td><b>Examples</b></td><td colspan="5">None</td></tr></tbody></table><table cellspacing="3" cellpadding="3" width="90%" border="0"><tbody><tr bgcolor="#cccccc"><td colspan="5"><b><font size="+1"><a name="swapCase">swapCase</a></font></b></td><td align="right" width="17%">Availability:&nbsp;1.0</td></tr><tr><td colspan="6"><p>Swap the casing in a String. Lowercase goes to Uppercase or Titlecase depending on whether they are the first in the String or after whitespace. Uppercase and Titlecase go to Lowercase </p></td></tr><tr><td width="15%"><b>Tag Body</b></td><td width="17%">JSP</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td></tr><tr><td><b>Restrictions</b></td><td colspan="5"><p>None</p></td></tr><tr><td><b>Attributes</b></td><td>Name</td><td>Required</td><td colspan="2">Runtime&nbsp;Expression&nbsp;Evaluation </td><td>Availability</td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>var</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Variable to store result in. </p></td></tr><tr><td><b>Variables</b></td><td colspan="5">None</td></tr><tr><td><b>Examples</b></td><td colspan="5">None</td></tr></tbody></table><table cellspacing="3" cellpadding="3" width="90%" border="0"><tbody><tr bgcolor="#cccccc"><td colspan="5"><b><font size="+1"><a name="soundex">soundex</a></font></b></td><td align="right" width="17%">Availability:&nbsp;1.0</td></tr><tr><td colspan="6"><p>Return the US_ENGLISH Soundex of a String. </p></td></tr><tr><td width="15%"><b>Tag Body</b></td><td width="17%">JSP</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td></tr><tr><td><b>Restrictions</b></td><td colspan="5"><p>None</p></td></tr><tr><td><b>Attributes</b></td><td>Name</td><td>Required</td><td colspan="2">Runtime&nbsp;Expression&nbsp;Evaluation </td><td>Availability</td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>var</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Variable to store result in. </p></td></tr><tr><td><b>Variables</b></td><td colspan="5">None</td></tr><tr><td><b>Examples</b></td><td colspan="5">None</td></tr></tbody></table><table cellspacing="3" cellpadding="3" width="90%" border="0"><tbody><tr bgcolor="#cccccc"><td colspan="5"><b><font size="+1"><a name="metaphone">metaphone</a></font></b></td><td align="right" width="17%">Availability:&nbsp;1.0</td></tr><tr><td colspan="6"><p>Get the metaphone for a String. This is an improved variant of SoundEx. </p></td></tr><tr><td width="15%"><b>Tag Body</b></td><td width="17%">JSP</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td></tr><tr><td><b>Restrictions</b></td><td colspan="5"><p>None</p></td></tr><tr><td><b>Attributes</b></td><td>Name</td><td>Required</td><td colspan="2">Runtime&nbsp;Expression&nbsp;Evaluation </td><td>Availability</td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>var</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Variable to store result in. </p></td></tr><tr><td><b>Variables</b></td><td colspan="5">None</td></tr><tr><td><b>Examples</b></td><td colspan="5">None</td></tr></tbody></table><table cellspacing="3" cellpadding="3" width="90%" border="0"><tbody><tr bgcolor="#cccccc"><td colspan="5"><b><font size="+1"><a name="quoteRegexp">quoteRegexp</a></font></b></td><td align="right" width="17%">Availability:&nbsp;1.0</td></tr><tr><td colspan="6"><p>Quote a String so that it will pass through a regular expression as a constant. </p></td></tr><tr><td width="15%"><b>Tag Body</b></td><td width="17%">JSP</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td></tr><tr><td><b>Restrictions</b></td><td colspan="5"><p>None</p></td></tr><tr><td><b>Attributes</b></td><td>Name</td><td>Required</td><td colspan="2">Runtime&nbsp;Expression&nbsp;Evaluation </td><td>Availability</td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>var</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Variable to store result in. </p></td></tr><tr><td><b>Variables</b></td><td colspan="5">None</td></tr><tr><td><b>Examples</b></td><td colspan="5">None</td></tr></tbody></table><table cellspacing="3" cellpadding="3" width="90%" border="0"><tbody><tr bgcolor="#cccccc"><td colspan="5"><b><font size="+1"><a name="capitalizeAllWords">capitalizeAllWords</a></font></b></td><td align="right" width="17%">Availability:&nbsp;1.0</td></tr><tr><td colspan="6"><p>Capitalize all the words found in a piece of body text. Capitalization is performed upon any letters following whitespace, and on the first character. </p></td></tr><tr><td width="15%"><b>Tag Body</b></td><td width="17%">JSP</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td></tr><tr><td><b>Restrictions</b></td><td colspan="5"><p>None</p></td></tr><tr><td><b>Attributes</b></td><td>Name</td><td>Required</td><td colspan="2">Runtime&nbsp;Expression&nbsp;Evaluation </td><td>Availability</td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>var</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Variable to store result in. </p></td></tr><tr><td><b>Variables</b></td><td colspan="5">None</td></tr><tr><td><b>Examples</b></td><td bgcolor="#cccccc" colspan="5">Will output: "Some Form Of Lower Case Sentence" &nbsp;</td></tr><tr><td>&nbsp;</td><td colspan="5"><p><pre><code>   &lt;str:capitalizeAllWords&gt;some form of lower case sentence&lt;/str:capitalizeAllWords&gt;                     </code> </pre><p></p></td></tr></tbody></table><table cellspacing="3" cellpadding="3" width="90%" border="0"><tbody><tr bgcolor="#cccccc"><td colspan="5"><b><font size="+1"><a name="removeXml">removeXml</a></font></b></td><td align="right" width="17%">Availability:&nbsp;1.0</td></tr><tr><td colspan="6"><p>Remove any XML tags from a String. A very simple algorithm which just removes any &lt;..&gt; blocks of text. </p></td></tr><tr><td width="15%"><b>Tag Body</b></td><td width="17%">JSP</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td></tr><tr><td><b>Restrictions</b></td><td colspan="5"><p>None</p></td></tr><tr><td><b>Attributes</b></td><td>Name</td><td>Required</td><td colspan="2">Runtime&nbsp;Expression&nbsp;Evaluation </td><td>Availability</td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>var</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Variable to store result in. </p></td></tr><tr><td><b>Variables</b></td><td colspan="5">None</td></tr><tr><td><b>Examples</b></td><td bgcolor="#cccccc" colspan="5">All it currently does is strip any &lt;xx&gt; tags out. It doesn't check that the tags are correct xml and it would be confused by &lt; or &gt; signs inside a tag attribute. &nbsp;</td></tr><tr><td>&nbsp;</td><td colspan="5"><p><pre><code>   &lt;str:removeXml&gt;&lt;name&gt;John Brown&lt;/name&gt;&lt;/str:removeXml&gt;                     </code> </pre><p></p></td></tr></tbody></table><table cellspacing="3" cellpadding="3" width="90%" border="0"><tbody><tr bgcolor="#cccccc"><td colspan="5"><b><font size="+1"><a name="encodeUrl">encodeUrl</a></font></b></td><td align="right" width="17%">Availability:&nbsp;1.0</td></tr><tr><td colspan="6"><p>Encode a String to that it may be used as a URL. <b>Note:</b> accented characters may not be encoded correctly, but there is not we can do about it (a solution would be passing the encoding as an attribute, but that would require a J2SE 1.4 environment). </p></td></tr><tr><td width="15%"><b>Tag Body</b></td><td width="17%">JSP</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td></tr><tr><td><b>Restrictions</b></td><td colspan="5"><p>None</p></td></tr><tr><td><b>Attributes</b></td><td>Name</td><td>Required</td><td colspan="2">Runtime&nbsp;Expression&nbsp;Evaluation </td><td>Availability</td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>var</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Variable to store result in. </p></td></tr><tr><td><b>Variables</b></td><td colspan="5">None</td></tr><tr><td><b>Examples</b></td><td bgcolor="#cccccc" colspan="5">Especially useful if database output is being put into an &lt;a href=".."&gt; &nbsp;</td></tr><tr><td>&nbsp;</td><td colspan="5"><p><pre><code>   &lt;str:encodeUrl&gt;http://www.apache.org/some file//page.html&lt;/str:encodeUrl&gt;                     </code> </pre><p></p></td></tr></tbody></table><table cellspacing="3" cellpadding="3" width="90%" border="0"><tbody><tr bgcolor="#cccccc"><td colspan="5"><b><font size="+1"><a name="decodeUrl">decodeUrl</a></font></b></td><td align="right" width="17%">Availability:&nbsp;1.0</td></tr><tr><td colspan="6"><p>Decode a URL so it may be nicely printed. <b>Note:</b> accented characters may not be encoded correctly, but there is not we can do about it (a solution would be passing the encoding as an attribute, but that would require a J2SE 1.4 environment). </p></td></tr><tr><td width="15%"><b>Tag Body</b></td><td width="17%">JSP</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td></tr><tr><td><b>Restrictions</b></td><td colspan="5"><p>None</p></td></tr><tr><td><b>Attributes</b></td><td>Name</td><td>Required</td><td colspan="2">Runtime&nbsp;Expression&nbsp;Evaluation </td><td>Availability</td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>var</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Variable to store result in. </p></td></tr><tr><td><b>Variables</b></td><td colspan="5">None</td></tr><tr><td><b>Examples</b></td><td bgcolor="#cccccc" colspan="5">Useful in parallel with its counterpart. If a database contains the URL in encoded form, then this could be used to show a human readable version. &nbsp;</td></tr><tr><td>&nbsp;</td><td colspan="5"><p><pre><code>   &lt;str:decodeUrl&gt;http://www.apache.org/some+file%20/page.html&lt;/str:decodeUrl&gt;                     </code> </pre><p></p></td></tr></tbody></table><table cellspacing="3" cellpadding="3" width="90%" border="0"><tbody><tr bgcolor="#cccccc"><td colspan="5"><b><font size="+1"><a name="count">count</a></font></b></td><td align="right" width="17%">Availability:&nbsp;1.0</td></tr><tr><td colspan="6"><p>Count the number of occurences of a passed in 'Set'. A Set is a String of a particular format. It may include ranges and single characters. A Set may be negated. <ul><li>range - "a-z" <li>char - "a" <li>negate - "^a" </li></ul><p></p></td></tr><tr><td width="15%"><b>Tag Body</b></td><td width="17%">JSP</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td></tr><tr><td><b>Restrictions</b></td><td colspan="5"><p>None</p></td></tr><tr><td><b>Attributes</b></td><td>Name</td><td>Required</td><td colspan="2">Runtime&nbsp;Expression&nbsp;Evaluation </td><td>Availability</td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>var</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Variable to store result in. </p></td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>set</b></td><td>&nbsp; Yes </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Character Set to look for. </p></td></tr><tr><td><b>Variables</b></td><td colspan="5">None</td></tr><tr><td><b>Examples</b></td><td bgcolor="#cccccc" colspan="5">There is 1 a, 2 e's and no f's. So the result is 3. &nbsp;</td></tr><tr><td>&nbsp;</td><td colspan="5"><p><pre><code>   &lt;str:count set="aef"&gt;Some sample text to count&lt;/count&gt;                     </code> </pre><p></p></td></tr></tbody></table><table cellspacing="3" cellpadding="3" width="90%" border="0"><tbody><tr bgcolor="#cccccc"><td colspan="5"><b><font size="+1"><a name="delete">delete</a></font></b></td><td align="right" width="17%">Availability:&nbsp;1.0</td></tr><tr><td colspan="6"><p>Delete any characters from the body that match characters specified in the Set. The syntax of a Set is described in Count. </p></td></tr><tr><td width="15%"><b>Tag Body</b></td><td width="17%">JSP</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td></tr><tr><td><b>Restrictions</b></td><td colspan="5"><p>None</p></td></tr><tr><td><b>Attributes</b></td><td>Name</td><td>Required</td><td colspan="2">Runtime&nbsp;Expression&nbsp;Evaluation </td><td>Availability</td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>var</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Variable to store result in. </p></td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>set</b></td><td>&nbsp; Yes </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Character Set to look for. </p></td></tr><tr><td><b>Variables</b></td><td colspan="5">None</td></tr><tr><td><b>Examples</b></td><td bgcolor="#cccccc" colspan="5">Will output: 'Som smpl txt to dlt rom' &nbsp;</td></tr><tr><td>&nbsp;</td><td colspan="5"><p><pre><code>   &lt;str:delete set="aef"&gt;Some sample text to delete from&lt;/str:delete&gt;                     </code> </pre><p></p></td></tr></tbody></table><table cellspacing="3" cellpadding="3" width="90%" border="0"><tbody><tr bgcolor="#cccccc"><td colspan="5"><b><font size="+1"><a name="squeeze">squeeze</a></font></b></td><td align="right" width="17%">Availability:&nbsp;1.0</td></tr><tr><td colspan="6"><p>Squeeze any characters from the body that match characters specified in the Set. Squeezing means that if it finds two adjoining characters that are the same, they are replaced with a single one of the characters. The syntax of a Set is described in the Count tag. </p></td></tr><tr><td width="15%"><b>Tag Body</b></td><td width="17%">JSP</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td></tr><tr><td><b>Restrictions</b></td><td colspan="5"><p>None</p></td></tr><tr><td><b>Attributes</b></td><td>Name</td><td>Required</td><td colspan="2">Runtime&nbsp;Expression&nbsp;Evaluation </td><td>Availability</td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>var</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Variable to store result in. </p></td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>set</b></td><td>&nbsp; Yes </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Character Set to look for. </p></td></tr><tr><td><b>Variables</b></td><td colspan="5">None</td></tr><tr><td><b>Examples</b></td><td bgcolor="#cccccc" colspan="5">Will output: 'Some sample text to squeeze' &nbsp;</td></tr><tr><td>&nbsp;</td><td colspan="5"><p><pre><code>   &lt;str:squeeze set="xo"&gt;Some sample texxxt toooo squeeze&lt;/str:squeeze&gt;                     </code> </pre><p></p></td></tr></tbody></table><table cellspacing="3" cellpadding="3" width="90%" border="0"><tbody><tr bgcolor="#cccccc"><td colspan="5"><b><font size="+1"><a name="center">center</a></font></b></td><td align="right" width="17%">Availability:&nbsp;1.0</td></tr><tr><td colspan="6"><p>Center the body String in a larger String of size width. </p></td></tr><tr><td width="15%"><b>Tag Body</b></td><td width="17%">JSP</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td></tr><tr><td><b>Restrictions</b></td><td colspan="5"><p>None</p></td></tr><tr><td><b>Attributes</b></td><td>Name</td><td>Required</td><td colspan="2">Runtime&nbsp;Expression&nbsp;Evaluation </td><td>Availability</td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>var</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Variable to store result in. </p></td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>delimiter</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>String to pad the larger String with. Default is a space character. </p></td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>width</b></td><td>&nbsp; Yes </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Size of larger String. </p></td></tr><tr><td><b>Variables</b></td><td colspan="5">None</td></tr><tr><td><b>Examples</b></td><td bgcolor="#cccccc" colspan="5">Outputs a header with 'The Title' embedded in a bunch of - characters. &nbsp;</td></tr><tr><td>&nbsp;</td><td colspan="5"><p><pre><code>   &lt;str:center width="40" delimiter="-"&gt;The Title&lt;/str:center&gt;                     </code> </pre><p></p></td></tr></tbody></table><table cellspacing="3" cellpadding="3" width="90%" border="0"><tbody><tr bgcolor="#cccccc"><td colspan="5"><b><font size="+1"><a name="rightPad">rightPad</a></font></b></td><td align="right" width="17%">Availability:&nbsp;1.0</td></tr><tr><td colspan="6"><p>Right pad a string with a particular delimiter to a specified width. The width includes the size of the string. </p></td></tr><tr><td width="15%"><b>Tag Body</b></td><td width="17%">JSP</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td></tr><tr><td><b>Restrictions</b></td><td colspan="5"><p>None</p></td></tr><tr><td><b>Attributes</b></td><td>Name</td><td>Required</td><td colspan="2">Runtime&nbsp;Expression&nbsp;Evaluation </td><td>Availability</td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>var</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Variable to store result in. </p></td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>delimiter</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>String to pad the larger String with. Default is a space character. </p></td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>width</b></td><td>&nbsp; Yes </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Size of larger String. </p></td></tr><tr><td><b>Variables</b></td><td colspan="5">None</td></tr><tr><td><b>Examples</b></td><td bgcolor="#cccccc" colspan="5">Will output: 'An arrow-------&gt;' &nbsp;</td></tr><tr><td>&nbsp;</td><td colspan="5"><p><pre><code>   &lt;str:rightPad width="15" delimiter="-"&gt;An arrow&lt;/str:rightPad&gt;&amp;gt;                     </code> </pre><p></p></td></tr></tbody></table><table cellspacing="3" cellpadding="3" width="90%" border="0"><tbody><tr bgcolor="#cccccc"><td colspan="5"><b><font size="+1"><a name="leftPad">leftPad</a></font></b></td><td align="right" width="17%">Availability:&nbsp;1.0</td></tr><tr><td colspan="6"><p>Left pad a string with a particular delimiter to a specified width. The width includes the size of the string. </p></td></tr><tr><td width="15%"><b>Tag Body</b></td><td width="17%">JSP</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td></tr><tr><td><b>Restrictions</b></td><td colspan="5"><p>None</p></td></tr><tr><td><b>Attributes</b></td><td>Name</td><td>Required</td><td colspan="2">Runtime&nbsp;Expression&nbsp;Evaluation </td><td>Availability</td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>var</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Variable to store result in. </p></td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>delimiter</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>String to pad the larger String with. Default is a space character. </p></td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>width</b></td><td>&nbsp; Yes </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Size of larger String. </p></td></tr><tr><td><b>Variables</b></td><td colspan="5">None</td></tr><tr><td><b>Examples</b></td><td bgcolor="#cccccc" colspan="5">Will output: '&lt;-------An arrow&gt;' &nbsp;</td></tr><tr><td>&nbsp;</td><td colspan="5"><p><pre><code>   &amp;lt;&lt;str:leftPad width="15" delimiter="-"&gt;An arrow&lt;/str:rightPad&gt;                     </code> </pre><p></p></td></tr></tbody></table><table cellspacing="3" cellpadding="3" width="90%" border="0"><tbody><tr bgcolor="#cccccc"><td colspan="5"><b><font size="+1"><a name="chomp">chomp</a></font></b></td><td align="right" width="17%">Availability:&nbsp;1.0</td></tr><tr><td colspan="6"><p>Remove the last occurence of a specified character, and everything after it. </p></td></tr><tr><td width="15%"><b>Tag Body</b></td><td width="17%">JSP</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td></tr><tr><td><b>Restrictions</b></td><td colspan="5"><p>None</p></td></tr><tr><td><b>Attributes</b></td><td>Name</td><td>Required</td><td colspan="2">Runtime&nbsp;Expression&nbsp;Evaluation </td><td>Availability</td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>var</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Variable to store result in. </p></td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>delimiter</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Character to remove after. Default is a newline character. </p></td></tr><tr><td><b>Variables</b></td><td colspan="5">None</td></tr><tr><td><b>Examples</b></td><td bgcolor="#cccccc" colspan="5">One use could be to remove # and // comments from code when outputted. &nbsp;</td></tr><tr><td>&nbsp;</td><td colspan="5"><p><pre><code>   &lt;str:chomp delimiter="#"&gt;Some code; # A comment&lt;/str:chomp&gt;                     </code> </pre><p></p></td></tr></tbody></table><table cellspacing="3" cellpadding="3" width="90%" border="0"><tbody><tr bgcolor="#cccccc"><td colspan="5"><b><font size="+1"><a name="getChomp">getChomp</a></font></b></td><td align="right" width="17%">Availability:&nbsp;1.0</td></tr><tr><td colspan="6"><p>Get everything after a specified delimiter. Returns the delimiter as well. </p></td></tr><tr><td width="15%"><b>Tag Body</b></td><td width="17%">JSP</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td></tr><tr><td><b>Restrictions</b></td><td colspan="5"><p>None</p></td></tr><tr><td><b>Attributes</b></td><td>Name</td><td>Required</td><td colspan="2">Runtime&nbsp;Expression&nbsp;Evaluation </td><td>Availability</td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>var</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Variable to store result in. </p></td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>delimiter</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Character to get text after. Default is a newline character. </p></td></tr><tr><td><b>Variables</b></td><td colspan="5">None</td></tr><tr><td><b>Examples</b></td><td bgcolor="#cccccc" colspan="5">Similarily to its counterpart, this could be used to get the comments from a piece of code. &nbsp;</td></tr><tr><td>&nbsp;</td><td colspan="5"><p><pre><code>   &lt;str:getChomp delimiter="#"&gt;Some code; # A comment&lt;/str:getChomp&gt;                     </code> </pre><p></p></td></tr></tbody></table><table cellspacing="3" cellpadding="3" width="90%" border="0"><tbody><tr bgcolor="#cccccc"><td colspan="5"><b><font size="+1"><a name="prechomp">prechomp</a></font></b></td><td align="right" width="17%">Availability:&nbsp;1.0</td></tr><tr><td colspan="6"><p>Remove everything up until a specified delimiter, and that specified delimiter from the start of a String. </p></td></tr><tr><td width="15%"><b>Tag Body</b></td><td width="17%">JSP</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td></tr><tr><td><b>Restrictions</b></td><td colspan="5"><p>None</p></td></tr><tr><td><b>Attributes</b></td><td>Name</td><td>Required</td><td colspan="2">Runtime&nbsp;Expression&nbsp;Evaluation </td><td>Availability</td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>var</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Variable to store result in. </p></td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>delimiter</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Character to remove before. Default is a newline character. </p></td></tr><tr><td><b>Variables</b></td><td colspan="5">None</td></tr><tr><td><b>Examples</b></td><td bgcolor="#cccccc" colspan="5">Again, this could be used to get the comment from a piece of code. However it would not include the delimiter as getChomp would. &nbsp;</td></tr><tr><td>&nbsp;</td><td colspan="5"><p><pre><code>   &lt;str:prechomp delimiter="#"&gt;Some code; # A comment&lt;/str:prechomp&gt;                     </code> </pre><p></p></td></tr></tbody></table><table cellspacing="3" cellpadding="3" width="90%" border="0"><tbody><tr bgcolor="#cccccc"><td colspan="5"><b><font size="+1"><a name="getPrechomp">getPrechomp</a></font></b></td><td align="right" width="17%">Availability:&nbsp;1.0</td></tr><tr><td colspan="6"><p>Get everything up until a specific delimiter. Returns the delimiter as well. </p></td></tr><tr><td width="15%"><b>Tag Body</b></td><td width="17%">JSP</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td></tr><tr><td><b>Restrictions</b></td><td colspan="5"><p>None</p></td></tr><tr><td><b>Attributes</b></td><td>Name</td><td>Required</td><td colspan="2">Runtime&nbsp;Expression&nbsp;Evaluation </td><td>Availability</td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>var</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Variable to store result in. </p></td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>delimiter</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Character to get text before. Default is a newline character. </p></td></tr><tr><td><b>Variables</b></td><td colspan="5">None</td></tr><tr><td><b>Examples</b></td><td bgcolor="#cccccc" colspan="5">In the code comment theme, this would return the code but include the comment character itself. &nbsp;</td></tr><tr><td>&nbsp;</td><td colspan="5"><p><pre><code>   &lt;str:getPrechomp delimiter="#"&gt;Some code; # A comment&lt;/str:getPrechomp&gt;                     </code> </pre><p></p></td></tr></tbody></table><table cellspacing="3" cellpadding="3" width="90%" border="0"><tbody><tr bgcolor="#cccccc"><td colspan="5"><b><font size="+1"><a name="strip">strip</a></font></b></td><td align="right" width="17%">Availability:&nbsp;1.0</td></tr><tr><td colspan="6"><p>Strip all of a specified character which appear at the start and end of a String. </p></td></tr><tr><td width="15%"><b>Tag Body</b></td><td width="17%">JSP</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td></tr><tr><td><b>Restrictions</b></td><td colspan="5"><p>None</p></td></tr><tr><td><b>Attributes</b></td><td>Name</td><td>Required</td><td colspan="2">Runtime&nbsp;Expression&nbsp;Evaluation </td><td>Availability</td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>var</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Variable to store result in. </p></td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>delimiter</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Character to remove from start and end of body. Default is a isWhitespace() character. </p></td></tr><tr><td><b>Variables</b></td><td colspan="5">None</td></tr><tr><td><b>Examples</b></td><td bgcolor="#cccccc" colspan="5">Default is isWhitespace, that is tab or newline or space character. &nbsp;</td></tr><tr><td>&nbsp;</td><td colspan="5"><p><pre><code>   &lt;str:strip delimiter="-"&gt;---A Title---&lt;/str:strip&gt;                     </code> </pre><p></p></td></tr></tbody></table><table cellspacing="3" cellpadding="3" width="90%" border="0"><tbody><tr bgcolor="#cccccc"><td colspan="5"><b><font size="+1"><a name="stripEnd">stripEnd</a></font></b></td><td align="right" width="17%">Availability:&nbsp;1.0</td></tr><tr><td colspan="6"><p>Strip all of a specified character which appear at the end of a String. </p></td></tr><tr><td width="15%"><b>Tag Body</b></td><td width="17%">JSP</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td></tr><tr><td><b>Restrictions</b></td><td colspan="5"><p>None</p></td></tr><tr><td><b>Attributes</b></td><td>Name</td><td>Required</td><td colspan="2">Runtime&nbsp;Expression&nbsp;Evaluation </td><td>Availability</td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>var</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Variable to store result in. </p></td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>delimiter</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Character to remove from end of body. Default is a isWhitespace() character. </p></td></tr><tr><td><b>Variables</b></td><td colspan="5">None</td></tr><tr><td><b>Examples</b></td><td bgcolor="#cccccc" colspan="5">&nbsp;</td></tr><tr><td>&nbsp;</td><td colspan="5"><p><pre><code>   &lt;str:stripEnd delimiter="-"&gt;A Title---&lt;/str:stripEnd&gt;                     </code> </pre><p></p></td></tr></tbody></table><table cellspacing="3" cellpadding="3" width="90%" border="0"><tbody><tr bgcolor="#cccccc"><td colspan="5"><b><font size="+1"><a name="stripStart">stripStart</a></font></b></td><td align="right" width="17%">Availability:&nbsp;1.0</td></tr><tr><td colspan="6"><p>Strip all of a specified character which appear at the start of a String. </p></td></tr><tr><td width="15%"><b>Tag Body</b></td><td width="17%">JSP</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td></tr><tr><td><b>Restrictions</b></td><td colspan="5"><p>None</p></td></tr><tr><td><b>Attributes</b></td><td>Name</td><td>Required</td><td colspan="2">Runtime&nbsp;Expression&nbsp;Evaluation </td><td>Availability</td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>var</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Variable to store result in. </p></td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>delimiter</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Character to remove from start of body. Default is a isWhitespace() character. </p></td></tr><tr><td><b>Variables</b></td><td colspan="5">None</td></tr><tr><td><b>Examples</b></td><td bgcolor="#cccccc" colspan="5">&nbsp;</td></tr><tr><td>&nbsp;</td><td colspan="5"><p><pre><code>   &lt;str:stripStart delimiter="-"&gt;---A Title&lt;/str:stripStart&gt;                     </code> </pre><p></p></td></tr></tbody></table><table cellspacing="3" cellpadding="3" width="90%" border="0"><tbody><tr bgcolor="#cccccc"><td colspan="5"><b><font size="+1"><a name="reverseDelimitedString">reverseDelimitedString</a></font></b></td><td align="right" width="17%">Availability:&nbsp;1.0</td></tr><tr><td colspan="6"><p>Reverses a delimited String. One example would be changing org.apache.taglib to taglib.apache.org. The delimiter to use is settable. </p></td></tr><tr><td width="15%"><b>Tag Body</b></td><td width="17%">JSP</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td></tr><tr><td><b>Restrictions</b></td><td colspan="5"><p>None</p></td></tr><tr><td><b>Attributes</b></td><td>Name</td><td>Required</td><td colspan="2">Runtime&nbsp;Expression&nbsp;Evaluation </td><td>Availability</td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>var</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Variable to store result in. </p></td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>delimiter</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Character to use as the delimiter in the qualified name. Default is a dot character. </p></td></tr><tr><td><b>Variables</b></td><td colspan="5">None</td></tr><tr><td><b>Examples</b></td><td bgcolor="#cccccc" colspan="5">Major use is to turn domain names into java package names. Bound to be other uses. &nbsp;</td></tr><tr><td>&nbsp;</td><td colspan="5"><p><pre><code>   &lt;str:reverseDelimitedString delimiter="."&gt;org.apache.taglib.string.String&lt;/str:reverseDelimitedString&gt;                     </code> </pre><p></p></td></tr></tbody></table><table cellspacing="3" cellpadding="3" width="90%" border="0"><tbody><tr bgcolor="#cccccc"><td colspan="5"><b><font size="+1"><a name="overlay">overlay</a></font></b></td><td align="right" width="17%">Availability:&nbsp;1.0</td></tr><tr><td colspan="6"><p>Overlay a String on top of another String. The length of the String to overlay does not have to be the same as the size of substring it replaces. </p></td></tr><tr><td width="15%"><b>Tag Body</b></td><td width="17%">JSP</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td></tr><tr><td><b>Restrictions</b></td><td colspan="5"><p>None</p></td></tr><tr><td><b>Attributes</b></td><td>Name</td><td>Required</td><td colspan="2">Runtime&nbsp;Expression&nbsp;Evaluation </td><td>Availability</td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>var</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Variable to store result in. </p></td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>with</b></td><td>&nbsp; Yes </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>String to overlay onto the body. </p></td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>start</b></td><td>&nbsp; Yes </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Start index. </p></td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>end</b></td><td>&nbsp; Yes </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Index to end before. </p></td></tr><tr><td><b>Variables</b></td><td colspan="5">None</td></tr><tr><td><b>Examples</b></td><td bgcolor="#cccccc" colspan="5">'pond' will be replaced by 'tree' &nbsp;</td></tr><tr><td>&nbsp;</td><td colspan="5"><p><pre><code>   &lt;str:overlay with="tree" start="4" end="8"&gt;The pond was wet.&lt;/str:overlay&gt;                     </code> </pre><p></p></td></tr></tbody></table><table cellspacing="3" cellpadding="3" width="90%" border="0"><tbody><tr bgcolor="#cccccc"><td colspan="5"><b><font size="+1"><a name="substring">substring</a></font></b></td><td align="right" width="17%">Availability:&nbsp;1.0</td></tr><tr><td colspan="6"><p>Get a specified substring from a larger String based on the start index and end-before index in the larger String </p></td></tr><tr><td width="15%"><b>Tag Body</b></td><td width="17%">JSP</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td></tr><tr><td><b>Restrictions</b></td><td colspan="5"><p>None</p></td></tr><tr><td><b>Attributes</b></td><td>Name</td><td>Required</td><td colspan="2">Runtime&nbsp;Expression&nbsp;Evaluation </td><td>Availability</td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>var</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Variable to store result in. </p></td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>start</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Start index. May be negative, which means it is the index counting backwards from the end of the string. Default is 0. </p></td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>end</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Index to end before. May be negative, which means it is the index counting backwards from the end of the string. May also be longer than the length of the string, in which case it quietly sets it to the length of the string. </p></td></tr><tr><td><b>Variables</b></td><td colspan="5">None</td></tr><tr><td><b>Examples</b></td><td bgcolor="#cccccc" colspan="5">Will get the substring 'tree' from the body. &nbsp;</td></tr><tr><td>&nbsp;</td><td colspan="5"><p><pre><code>   &lt;str:substring start="4" end="8"&gt;The tree is green.&lt;/str:substring&gt;                     </code> </pre><p></p></td></tr></tbody></table><table cellspacing="3" cellpadding="3" width="90%" border="0"><tbody><tr bgcolor="#cccccc"><td colspan="5"><b><font size="+1"><a name="repeat">repeat</a></font></b></td><td align="right" width="17%">Availability:&nbsp;1.0</td></tr><tr><td colspan="6"><p>Repeat a string a particular number of times. </p></td></tr><tr><td width="15%"><b>Tag Body</b></td><td width="17%">JSP</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td></tr><tr><td><b>Restrictions</b></td><td colspan="5"><p>None</p></td></tr><tr><td><b>Attributes</b></td><td>Name</td><td>Required</td><td colspan="2">Runtime&nbsp;Expression&nbsp;Evaluation </td><td>Availability</td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>var</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Variable to store result in. </p></td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>count</b></td><td>&nbsp; Yes </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Number of times to repeat the body. </p></td></tr><tr><td><b>Variables</b></td><td colspan="5">None</td></tr><tr><td><b>Examples</b></td><td bgcolor="#cccccc" colspan="5">Will output 'xxxxx' &nbsp;</td></tr><tr><td>&nbsp;</td><td colspan="5"><p><pre><code>   &lt;str:repeat count="5"&gt;x&lt;/str:repeat&gt;                     </code> </pre><p></p></td></tr></tbody></table><table cellspacing="3" cellpadding="3" width="90%" border="0"><tbody><tr bgcolor="#cccccc"><td colspan="5"><b><font size="+1"><a name="wordWrap">wordWrap</a></font></b></td><td align="right" width="17%">Availability:&nbsp;1.0</td></tr><tr><td colspan="6"><p>Word-wrap a String. This involves formatting a long String to fit within a certain character width of page. A delimiter may be passed in to put at the end of each line and a splitting character can be specified for when a word has to be cut in half. </p></td></tr><tr><td width="15%"><b>Tag Body</b></td><td width="17%">JSP</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td></tr><tr><td><b>Restrictions</b></td><td colspan="5"><p>None</p></td></tr><tr><td><b>Attributes</b></td><td>Name</td><td>Required</td><td colspan="2">Runtime&nbsp;Expression&nbsp;Evaluation </td><td>Availability</td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>var</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Variable to store result in. </p></td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>width</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Width to word wrap to. Default is 80. </p></td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>delimiter</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Character to put between each line. Default is a newline character. </p></td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>split</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Character to use when a word has to be split. Default is a - character. </p></td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>delimiterInside</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; No </td><td>&nbsp;1.1</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Flag indicating if the delimiter should be included in chunk before length reaches width. Default is true. </p></td></tr><tr><td><b>Variables</b></td><td colspan="5">None</td></tr><tr><td><b>Examples</b></td><td bgcolor="#cccccc" colspan="5">&nbsp;</td></tr><tr><td>&nbsp;</td><td colspan="5"><p><pre><code>   &lt;str:wordWrap width ="50" delimiter="&amp;lt;br&amp;gt;"&gt;Word-wrap a String. This involves formatting a long String to fit within a certain character width of page. A delimiter may be passed in to put at the end of each line and a splitting character can be specified for when a word has to be cut in half.&lt;/str:wordWrap&gt;                     </code> </pre><p></p></td></tr></tbody></table><table cellspacing="3" cellpadding="3" width="90%" border="0"><tbody><tr bgcolor="#cccccc"><td colspan="5"><b><font size="+1"><a name="nestedString">nestedString</a></font></b></td><td align="right" width="17%">Availability:&nbsp;1.0</td></tr><tr><td colspan="6"><p>Get a String that is nested between an open and closing substring. </p></td></tr><tr><td width="15%"><b>Tag Body</b></td><td width="17%">JSP</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td></tr><tr><td><b>Restrictions</b></td><td colspan="5"><p>None</p></td></tr><tr><td><b>Attributes</b></td><td>Name</td><td>Required</td><td colspan="2">Runtime&nbsp;Expression&nbsp;Evaluation </td><td>Availability</td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>var</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Variable to store result in. </p></td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>open</b></td><td>&nbsp; Yes </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Index to start substring at. </p></td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>close</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Index to stop substring before. Default is the end of the string. </p></td></tr><tr><td><b>Variables</b></td><td colspan="5">None</td></tr><tr><td><b>Examples</b></td><td bgcolor="#cccccc" colspan="5">Pluck's 'Bob' from out of the square brackets. &nbsp;</td></tr><tr><td>&nbsp;</td><td colspan="5"><p><pre><code>   &lt;str:nestedString open="[" close="]"&gt;[Bob]&lt;/str:nestedString&gt;                     </code> </pre><p></p></td></tr></tbody></table><table cellspacing="3" cellpadding="3" width="90%" border="0"><tbody><tr bgcolor="#cccccc"><td colspan="5"><b><font size="+1"><a name="countMatches">countMatches</a></font></b></td><td align="right" width="17%">Availability:&nbsp;1.0</td></tr><tr><td colspan="6"><p>Return the number of times that the body String contains the sub-string. </p></td></tr><tr><td width="15%"><b>Tag Body</b></td><td width="17%">JSP</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td></tr><tr><td><b>Restrictions</b></td><td colspan="5"><p>None</p></td></tr><tr><td><b>Attributes</b></td><td>Name</td><td>Required</td><td colspan="2">Runtime&nbsp;Expression&nbsp;Evaluation </td><td>Availability</td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>var</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Variable to store result in. </p></td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>substring</b></td><td>&nbsp; Yes </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Substring to count number of. </p></td></tr><tr><td><b>Variables</b></td><td colspan="5">None</td></tr><tr><td><b>Examples</b></td><td bgcolor="#cccccc" colspan="5">The substring 'world' is repeated four times in the body. &nbsp;</td></tr><tr><td>&nbsp;</td><td colspan="5"><p><pre><code>   &lt;str:countMatches substring="world"&gt;Hello world programs are rife in this world due to their worldy view of how to program a world of code&lt;/str:countMatches&gt;                     </code> </pre><p></p></td></tr></tbody></table><table cellspacing="3" cellpadding="3" width="90%" border="0"><tbody><tr bgcolor="#cccccc"><td colspan="5"><b><font size="+1"><a name="default">default</a></font></b></td><td align="right" width="17%">Availability:&nbsp;1.0</td></tr><tr><td colspan="6"><p>If the body String is a particular value, then output a default value, else output the body String. The major use of this is to convert 'null' into an empty String. </p></td></tr><tr><td width="15%"><b>Tag Body</b></td><td width="17%">JSP</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td></tr><tr><td><b>Restrictions</b></td><td colspan="5"><p>None</p></td></tr><tr><td><b>Attributes</b></td><td>Name</td><td>Required</td><td colspan="2">Runtime&nbsp;Expression&nbsp;Evaluation </td><td>Availability</td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>var</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Variable to store result in. </p></td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>value</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Value to be equal to. Default is the string: "null". </p></td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>default</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Value to place if body is equal to value field. Default is an empty String. </p></td></tr><tr><td><b>Variables</b></td><td colspan="5">None</td></tr><tr><td><b>Examples</b></td><td bgcolor="#cccccc" colspan="5">If the inner tag (db:get) return null (or the string "null") then an empty string will be printed out. &nbsp;</td></tr><tr><td>&nbsp;</td><td colspan="5"><p><pre><code>   &lt;str:default&gt;&lt;db:get value="Name"&gt;&lt;/str:default&gt;                     </code> </pre><p></p></td></tr></tbody></table><table cellspacing="3" cellpadding="3" width="90%" border="0"><tbody><tr bgcolor="#cccccc"><td colspan="5"><b><font size="+1"><a name="replace">replace</a></font></b></td><td align="right" width="17%">Availability:&nbsp;1.0</td></tr><tr><td colspan="6"><p>Replace a specified substring with another string. A number of times may be specified to say how many times to replace the substring. </p></td></tr><tr><td width="15%"><b>Tag Body</b></td><td width="17%">JSP</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td></tr><tr><td><b>Restrictions</b></td><td colspan="5"><p>None</p></td></tr><tr><td><b>Attributes</b></td><td>Name</td><td>Required</td><td colspan="2">Runtime&nbsp;Expression&nbsp;Evaluation </td><td>Availability</td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>var</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Variable to store result in. </p></td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>replace</b></td><td>&nbsp; Yes </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Value to find to replace. </p></td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>with</b></td><td>&nbsp; Yes </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Value to replace with. </p></td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>count</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Number of times to replace. Default is all matches. </p></td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>newlineToken</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0.1</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Token to use instead of a newline to get around JSP pain. Default is to ignore this functionality. </p></td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>carriageToken</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0.1</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Token to use instead of a carriage return to get around JSP pain. Default is to ignore this functionality. </p></td></tr><tr><td><b>Variables</b></td><td colspan="5">None</td></tr><tr><td><b>Examples</b></td><td bgcolor="#cccccc" colspan="5">One use of the replace tag is to change newlines to html br's. Note that real newlines need to be entered into the JSP. &nbsp;</td></tr><tr><td>&nbsp;</td><td colspan="5"><p><pre><code>   &lt;str:replace replace=" " with="&amp;lt;br&amp;gt; "&gt;A sentence. Another sentence. Some more to test. And insert Br's into. Hopefully.&lt;/str:replace&gt;         _or_ with 1.0.1:   &lt;str:replace replace="NL" with="&amp;lt;br&amp;gt;NL" newlineToken="NL"&gt; A sentence. Another sentence. Some more to test. And insert Br's into. Hopefully.&lt;/str:replace&gt;                     </code> </pre><p></p></td></tr></tbody></table><table cellspacing="3" cellpadding="3" width="90%" border="0"><tbody><tr bgcolor="#cccccc"><td colspan="5"><b><font size="+1"><a name="randomString">randomString</a></font></b></td><td align="right" width="17%">Availability:&nbsp;1.0</td></tr><tr><td colspan="6"><p>Create a random string. It can create an ascii string, a numeric string, an alphanumeric string, and a unicode string. The size of the string may be specified, as can a start and end character. Lastly, a set of characters to use may be passed in. </p></td></tr><tr><td width="15%"><b>Tag Body</b></td><td width="17%">JSP</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td></tr><tr><td><b>Restrictions</b></td><td colspan="5"><p>None</p></td></tr><tr><td><b>Attributes</b></td><td>Name</td><td>Required</td><td colspan="2">Runtime&nbsp;Expression&nbsp;Evaluation </td><td>Availability</td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>var</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Variable to store result in. </p></td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>count</b></td><td>&nbsp; Yes </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Number of characters to generate. </p></td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>start</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Start of range of characters to generate from. Linked to type attribute. </p></td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>end</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>End of range of characters to generate from. Linked to type attribute. </p></td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>type</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Type of random-string. One of: numeric | alphanumeric | alphabet | unicode. Default value is to unicode. </p></td></tr><tr><td><b>Variables</b></td><td colspan="5">None</td></tr><tr><td><b>Examples</b></td><td bgcolor="#cccccc" colspan="5">The random tag has a lot of options. The easiest way is to just use the type field, as in the example. The second example shows how the developer can specify the characters to use, for example, random vowels. The last example is merely demonstrative, no one would want to do this, but it shows how the developer may specify the range of characters, in this example, all the control characters. &nbsp;</td></tr><tr><td>&nbsp;</td><td colspan="5"><p><pre><code>   &lt;str:random count="10" type="alphanumeric"/&gt; &lt;str:random count="1"&gt;aeiou&lt;/str:random&gt; &lt;str:random count="5" start="1" end="32"/&gt;                     </code> </pre><p></p></td></tr></tbody></table><table cellspacing="3" cellpadding="3" width="90%" border="0"><tbody><tr bgcolor="#cccccc"><td colspan="5"><b><font size="+1"><a name="left">left</a></font></b></td><td align="right" width="17%">Availability:&nbsp;1.0</td></tr><tr><td colspan="6"><p>Get the leftmost 'n' characters from a string. </p></td></tr><tr><td width="15%"><b>Tag Body</b></td><td width="17%">JSP</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td></tr><tr><td><b>Restrictions</b></td><td colspan="5"><p>None</p></td></tr><tr><td><b>Attributes</b></td><td>Name</td><td>Required</td><td colspan="2">Runtime&nbsp;Expression&nbsp;Evaluation </td><td>Availability</td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>var</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Variable to store result in. </p></td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>count</b></td><td>&nbsp; Yes </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Number of characters to get. </p></td></tr><tr><td><b>Variables</b></td><td colspan="5">None</td></tr><tr><td><b>Examples</b></td><td bgcolor="#cccccc" colspan="5">Will output: '&lt;A long piece of&gt;' &nbsp;</td></tr><tr><td>&nbsp;</td><td colspan="5"><p><pre><code>   &amp;lt;&lt;str:left count="15"&gt;A long piece of text which will get cut.&lt;/str:rightPad&gt;                     </code> </pre><p></p></td></tr></tbody></table><table cellspacing="3" cellpadding="3" width="90%" border="0"><tbody><tr bgcolor="#cccccc"><td colspan="5"><b><font size="+1"><a name="right">right</a></font></b></td><td align="right" width="17%">Availability:&nbsp;1.0</td></tr><tr><td colspan="6"><p>Get the rightmost 'n' characters from a string. </p></td></tr><tr><td width="15%"><b>Tag Body</b></td><td width="17%">JSP</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td></tr><tr><td><b>Restrictions</b></td><td colspan="5"><p>None</p></td></tr><tr><td><b>Attributes</b></td><td>Name</td><td>Required</td><td colspan="2">Runtime&nbsp;Expression&nbsp;Evaluation </td><td>Availability</td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>var</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Variable to store result in. </p></td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>count</b></td><td>&nbsp; Yes </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Number of characters to get. </p></td></tr><tr><td><b>Variables</b></td><td colspan="5">None</td></tr><tr><td><b>Examples</b></td><td bgcolor="#cccccc" colspan="5">Will output: '&lt;will get cut.&gt;' &nbsp;</td></tr><tr><td>&nbsp;</td><td colspan="5"><p><pre><code>   &amp;lt;&lt;str:right count="13"&gt;A long piece of text which will get cut.&lt;/str:rightPad&gt;                     </code> </pre><p></p></td></tr></tbody></table><table cellspacing="3" cellpadding="3" width="90%" border="0"><tbody><tr bgcolor="#cccccc"><td colspan="5"><b><font size="+1"><a name="mid">mid</a></font></b></td><td align="right" width="17%">Availability:&nbsp;1.0</td></tr><tr><td colspan="6"><p>Get 'n' characters from the inside of a string. The start position may be set, or the default may be used. The default is to get the central characters. </p></td></tr><tr><td width="15%"><b>Tag Body</b></td><td width="17%">JSP</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td></tr><tr><td><b>Restrictions</b></td><td colspan="5"><p>None</p></td></tr><tr><td><b>Attributes</b></td><td>Name</td><td>Required</td><td colspan="2">Runtime&nbsp;Expression&nbsp;Evaluation </td><td>Availability</td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>var</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Variable to store result in. </p></td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>start</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Position to start at. </p></td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>count</b></td><td>&nbsp; Yes </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Number of characters to get. </p></td></tr><tr><td><b>Variables</b></td><td colspan="5">None</td></tr><tr><td><b>Examples</b></td><td bgcolor="#cccccc" colspan="5">Will output: '&lt;text which&gt;' &nbsp;</td></tr><tr><td>&nbsp;</td><td colspan="5"><p><pre><code>   &amp;lt;&lt;str:mid count="10"&gt;A long piece of text which will get cut.&lt;/str:rightPad&gt;                     </code> </pre><p></p></td></tr></tbody></table><table cellspacing="3" cellpadding="3" width="90%" border="0"><tbody><tr bgcolor="#cccccc"><td colspan="5"><b><font size="+1"><a name="truncateNicely">truncateNicely</a></font></b></td><td align="right" width="17%">Availability:&nbsp;1.0</td></tr><tr><td colspan="6"><p>A more intelligent substring. It attempts to cut off a string after a space, following predefined or user-supplied lower and upper limits, useful for making short descriptions from long text. It strips the HTML out as a part of the code. Patches on a version which doesn't strip the HTML will be gratefully received. </p></td></tr><tr><td width="15%"><b>Tag Body</b></td><td width="17%">JSP</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td></tr><tr><td><b>Restrictions</b></td><td colspan="5"><p>None</p></td></tr><tr><td><b>Attributes</b></td><td>Name</td><td>Required</td><td colspan="2">Runtime&nbsp;Expression&nbsp;Evaluation </td><td>Availability</td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>var</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Variable to store result in. </p></td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>lower</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Mininum length to truncate at. </p></td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>upper</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Maximum length the string can be. Will force a truncate at this point. </p></td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>appendToEnd</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>String to append to the end of the truncated string. </p></td></tr><tr><td><b>Variables</b></td><td colspan="5">None</td></tr><tr><td><b>Examples</b></td><td bgcolor="#cccccc" colspan="5">Will output: '&lt;The quick brown...&gt;' &nbsp;</td></tr><tr><td>&nbsp;</td><td colspan="5"><p><pre><code>   &amp;lt;&lt;str:truncateNicely lower="13" upper="20"&gt;The quick brown fox jumped over the lazy dog.&lt;/str:truncateNicely&gt;                     </code> </pre><p></p></td></tr></tbody></table><table cellspacing="3" cellpadding="3" width="90%" border="0"><tbody><tr bgcolor="#cccccc"><td colspan="5"><b><font size="+1"><a name="join">join</a></font></b></td><td align="right" width="17%">Availability:&nbsp;1.1</td></tr><tr><td colspan="6"><p>Joins the elements of the provided array. </p></td></tr><tr><td width="15%"><b>Tag Body</b></td><td width="17%">EMPTY</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td></tr><tr><td><b>Restrictions</b></td><td colspan="5"><p>None</p></td></tr><tr><td><b>Attributes</b></td><td>Name</td><td>Required</td><td colspan="2">Runtime&nbsp;Expression&nbsp;Evaluation </td><td>Availability</td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>items</b></td><td>&nbsp; Yes </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.1</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Array of elements to be joined. </p></td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>separator</b></td><td>&nbsp; No </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.1</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Separator string to be used. </p></td></tr><tr><td><b>Variables</b></td><td colspan="5">None</td></tr><tr><td><b>Examples</b></td><td bgcolor="#cccccc" colspan="5">Useful to join elements of a list. &nbsp;</td></tr><tr><td>&nbsp;</td><td colspan="5"><p><pre><code>  &lt;% String[] users = new String[] { "john", "bob", "alice", "felipe" }; %&gt; &lt;str:join items="&lt;%=users%&gt;" separator=" - "/&gt;                     </code> </pre><p></p></td></tr></tbody></table><table cellspacing="3" cellpadding="3" width="90%" border="0"><tbody><tr bgcolor="#cccccc"><td colspan="5"><b><font size="+1"><a name="split">split</a></font></b></td><td align="right" width="17%">Availability:&nbsp;1.1</td></tr><tr><td colspan="6"><p>Splits the provided text into an array, separators specified. The separator is not included in the returned String array and adjacent separators are treated as one separator. </p></td></tr><tr><td width="15%"><b>Tag Body</b></td><td width="17%">JSP</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td><td width="17%">&nbsp;</td></tr><tr><td><b>Restrictions</b></td><td colspan="5"><p>None</p></td></tr><tr><td><b>Attributes</b></td><td>Name</td><td>Required</td><td colspan="2">Runtime&nbsp;Expression&nbsp;Evaluation </td><td>Availability</td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>separator</b></td><td>&nbsp; Yes </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.1</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Separator string to be used. </p></td></tr><tr bgcolor="#cccccc"><td bgcolor="#ffffff">&nbsp;</td><td><b>var</b></td><td>&nbsp; Yes </td><td colspan="2">&nbsp; Yes </td><td>&nbsp;1.0</td></tr><tr><td bgcolor="#ffffff">&nbsp;</td><td colspan="5"><p>Variable to store result in. </p></td></tr><tr><td><b>Variables</b></td><td colspan="5">None</td></tr><tr><td><b>Examples</b></td><td bgcolor="#cccccc" colspan="5">This is the reverse of join and is the equivalent of StringTokenizer in a tag. &nbsp;</td></tr><tr><td>&nbsp;</td><td colspan="5"><p><pre><code>  &lt;% &lt;str:split separator=" - " var="users"&gt;john - bob - alice - felipe&lt;/str:split&gt;                     </code> </pre><p></p></td></tr></tbody></table><a name="examples"><h3>Examples</h3></a><p>See the example application string-examples.war for examples of the usage of the tags from this custom tag library.</p><a name="javadocs"><h3>Java Docs</h3></a><p>Java programmers can view the java class documentation for this tag library as <a href="http://jakarta.apache.org/taglibs/doc/string-doc/javadoc/index.html">javadocs</a>.</p><a name="history"><h3>Revision History</h3></a><p>Review the complete <a href="http://jakarta.apache.org/taglibs/doc/string-doc/changes.html">revision history</a> of this tag library.</p>			 ]]> 
		</description>

		<comments>http://namkee.egloos.com/3121949#comments</comments>
		<pubDate>Tue, 20 Feb 2007 01:27:06 GMT</pubDate>
		<dc:creator>namkee</dc:creator>
	</item>
	<item>
		<title><![CDATA[ The Spring Framework Reference Docu Ch.1 소개 ]]> </title>
		<link>http://namkee.egloos.com/3085954</link>
		<guid>http://namkee.egloos.com/3085954</guid>
		<description>
			<![CDATA[ 
  <div class="titlepage"><h2 class="title">Chapter&nbsp;1.&nbsp;소개</h2><br />
<br />
<br />
</div><div class="sect1" lang="en"><div class="titlepage"><h2 class="title" style="CLEAR: both"><a name="introduction-overview"></a>1.1.&nbsp;개요</h2><br />
<br />
<br />
</div><p>Spring은&nbsp;아래&nbsp;다이어그램에서 보여지는 7개의 모듈로 잘 조직된 많은 기능과 특성들로 이루어져 있다. 이 장은 순서대로 각 모듈을 언급한다. </p><p></p><div class="mediaobject" align="center"><div style="text-align:center"><img class="image_mid" border="0" onmouseover="this.style.cursor='pointer'" alt="" src="http://pds5.egloos.com/pds/200702/12/95/c0043595_10022299.gif" width="500" height="264.668367347" onclick="Control.Modal.openDialog(this, event, 'http://pds5.egloos.com/pds/200702/12/95/c0043595_10022299.gif');" /></div><br />
<div class="caption"><p>Spring 프레임워크의 개요 </p></div></div><p></p><p>&nbsp;Core Package는 프레임워크의 가장 기본적인 부분이고 IoC와 의존성 삽입(Dependency Injection-DI)기능을 제공한다. 여기에 나타는 기본적인 개념인 BeanFactory는 프로그램에 따르게 되는 Singleton을 없애고 환경설정과 실제 프로그램 로직 내에서의 의존성에 대한 기술을 불리시키는 Factory 패턴이다. </p><p>&nbsp;Core Package위에는 Framework 스타일의 Bean에 접근 방법을 제공하는 (다소 JNDI-registry와 비슷한)Context Package가 있다.&nbsp;Context Package는 Bean Package로부터&nbsp;특성을 상속받고, 텍스트 메세지 지원, 이벤트 전달, 리소스로딩과 Context의 생성(예를 들어 서블릿 콘테이너에 의한)등의 부가적인 기능도 가진다. </p><p>&nbsp;DAO Package는 지겨운 JDBC코딩과 Database 벤더의 특정 에러코드 파싱 작업으로부터 해방시켜줄 JDBC 추상화 레이어를 제공한다. 또한 JDBC Package는 선언적 트랜잭션 관리를 통해(특정 인터페이스 구현으로만이 아니라 스스로 작성한 POJO를 통해서도)&nbsp;프로그래밍을 편하게 해준다. </p><p>&nbsp;ORM Package는 대중적인 OR매핑 API들(JDO를 포함해서 Hiberante, iBatis 등)을 통합할수 있는 레이어를 제공한다. ORM Package를 통해서 앞에 이야기한 선언적 트랜잭션 관리와 같은 Spring이 제공하는 기능들을 조합해서 모든 OR매핑을 사용할 수 있다. </p><p>&nbsp;AOP Package는 Aspect-Oriented Programming 구현을 정의하고 따르도록 하는 기능을 제공한다. 예를 들면 메소드 인터셉터와 Pointcut은 논리적으로 반드시 분리되어야 하기 때문에 기능적으로 명확하게 분리된 코드를 구현한다. 기능적인 소스레벨의 메타데이터를 사용해서 코드안에 실행되어야할 정보를 조합할수 있다. .NET의 속성과 약간 비슷하다. </p><p>&nbsp;Web Package는 멀티파트 기능, 서블릿 리스너를 사용한 Context의 초기화, 웹 기반 Application 등과같은 웹기반 통합 기능을 제공한다. Spring을 WebWork나 Strutsrk같은 Package는&nbsp;함께 통합될수 있다.</p><p>&nbsp;Spring MVC Package는&nbsp;웹 Application을 위한 Model-View-Controller(MVC)구현을 할 수 있도록 한다. Spring의 MVC구현은 그냥 보통의 구현이 아니다. 도메인 모델의 코드와&nbsp;Web Form코드가 명확하게 분리되도록 하며 유효성체크와 같은 Spring의&nbsp;다른 기능들을 사용할수 있도록 해준다.&nbsp;</p></div><div class="sect1" lang="en"><div class="titlepage"><h2 class="title" style="CLEAR: both"><a name="overview-usagescenarios"></a>1.2.&nbsp;사용 시나리오</h2><br />
<br />
<br />
</div><p>&nbsp;위에서 언급된 Building Blocks를 통해 애플릿에서부터 Spring의 트랜잭션 관리 기능과 웹 프레임워크를 사용하는 완전한 기업용 애플리케이션까지 모든 종류의 시나리오로 Spring을 사용할수 있다. </p><p></p><div class="mediaobject" align="center">&nbsp; <div style="text-align:center"><img class="image_mid" border="0" onmouseover="this.style.cursor='pointer'" alt="" src="http://pds4.egloos.com/pds/200702/12/95/c0043595_10025927.gif" width="500" height="339.40397351" onclick="Control.Modal.openDialog(this, event, 'http://pds4.egloos.com/pds/200702/12/95/c0043595_10025927.gif');" /></div><br />
<div class="caption"><p>전형적인 완전한 Spring웹 애플리케이션 </p></div></div><p></p><p><tt class="literal">TransactionProxyFactoryBeans는 EJB 웹&nbsp;Apllication</tt>&nbsp;에서 제공되는 Container관리 Transaction 처럼 완벽하게 트랜잭션적이다. 비즈니스 로직은 Dependancy Injection 컨테이너에 의해 관리되는 간단한 POJO를 통해서 구현될 수 있다. 메일을 보내거나 유효성 체크를 위한 지원을 포함하는 서비스, 웹 레이어의 비의존성은 당신에게 유효성체크 규칙을 수행하기 위한 위치를 선택하도록 허용한다. Spring의 OR 매핑 지원은 Hibernate, JDO 그리고 iBatis와 통합된다. </p><p>&nbsp;당신의 모든 사용자 지정 비지니스 로직은 Spring의 의존성 삽입 컨테이너에 의해 관리되는 간단한 POJO를 사용해서 구현될수 있다. 메일을 보내거나 유효성체크를 위한 지원을 포함하는 서비스, 웹 레이어의 비의존성은 당신에게 유효성체크 규칙을 수행하기 위한 위치를 선택하도록 허용한다. Spring의 ORM지원은 Hibernate, JDO 그리고 iBATIS와 통합된다. 예를 들어 Hibernate를 사용할때 당신은 존재하는 Hibernate맵핑을 지속적으로 사용하고 표준 Hibernate <tt class="classname">SessionFactory</tt>설정을 사용할수 있다. 폼 컨트롤러는 <tt class="classname">ActionForms</tt>이나 HTTP파라미터를 당신의 도메인 모델을 위한 값에 이동시키는 다른 클래스의 필요성을 제거하는 도메인모델을 가진 웹레이어와 유사하게 통합한다. </p><p></p><div class="mediaobject" align="center"><img src="http://openframework.or.kr/framework_reference/spring/ver2.0-M4/html/images/thirdparty-web.gif" align="middle" /> <div class="caption"><p>3자(third-party)의 웹 프레임워크를 사용한 Spring 미들티어 </p></div></div><p></p><p>때때로 현재의 환경은 당신에게 다른 프레임워크로의 완벽한 교체를 허용하지 않는다. Spring은 이것내 모든것을 사용하도록 당신에게 강요하지 <font size="+0"><em>않는다</em></font>. 이것은 <font size="+0"><em>모든것 또는 아무것도 아닌것(all-or-nothing)</em></font>인 솔루션이 아니다. WebWork, Struts, Tapestry 또는 다른 UI프레임워크를 사용한 존재하는 앞부분은 당신에게 Spring이 제공하는 트랜잭션 기능을 사용하도록 허용하는 Spring기반의 미들티어와 완벽하게 통합될수 있다. 당신이 해야할 필요가 있는 오직 한가지는 <tt class="classname">ApplicationContext</tt>를 사용하여 당신의 비지니스 로직을 묶고 <tt class="classname">WebApplicationContext</tt>를 사용하여 당신의 웹 UI레이어를 통합하는 것이다. </p><p></p><div class="mediaobject" align="center"><img src="http://openframework.or.kr/framework_reference/spring/ver2.0-M4/html/images/remoting.gif" align="middle" /> <div class="caption"><p>원격 사용 시나리오 </p></div></div><p></p><p>당신이 웹서비스를 통해 존재하는 코드에 접근할 필요가 있을 때, 당신은 Spring의 <tt class="literal">Hessian-</tt>, <tt class="literal">Burlap-</tt>, <tt class="literal">Rmi-</tt> 나 <tt class="literal">JaxRpcProxyFactory</tt>클래스를 사용할수 있다. 존재하는 애플리케이션에 원격 접근을 가능하게 하는 것은 최근에는 어려운 일이 아니다. </p><p></p><div class="mediaobject" align="center"><img src="http://openframework.or.kr/framework_reference/spring/ver2.0-M4/html/images/ejb.gif" align="middle" /> <div class="caption"><p>EJB - 존재하는 POJO를 포장하기 </p></div></div><p></p><p>Spring은 POJO를 재사용하는것을 당신에게 허용하고 그것들을 비상태유지(stateless) 세션빈으로 포장하고 선언적인 보안이 필요한 측정가능한 실패에 안전한(failsafe) 웹 애플리케이션내 사용하기 위한 EJB를 위해 존재하는 <a title="Chapter&nbsp;19.&nbsp;EJB에 접근하고 구현하기" href="http://openframework.or.kr/framework_reference/spring/ver2.0-M4/html/ejb.html">접근- 그리고 추상- 레이어</a>를 제공한다. </p></div>			 ]]> 
		</description>
		<category>Task</category>

		<comments>http://namkee.egloos.com/3085954#comments</comments>
		<pubDate>Fri, 09 Feb 2007 02:57:46 GMT</pubDate>
		<dc:creator>namkee</dc:creator>
	</item>
	<item>
		<title><![CDATA[  J2EE Development without EJB (5) - EJB, Five Years On ]]> </title>
		<link>http://namkee.egloos.com/3082415</link>
		<guid>http://namkee.egloos.com/3082415</guid>
		<description>
			<![CDATA[ 
  <p>출처 : http://toby.epril.com</p><p>원본 : http://toby.epril.com/?p=47</p><p><br />
</p><p>J2EE Development without EJB에는 정말 갈수록 방대한 양의 정보가 있다. 정리해 놓기도 만만치 않다. 그러나 그 수고는 충분히 가치있다고 생각된다. 전세계 수많은 뛰어난 J2EE개발자들의 경험과 생각이 녹아있는 책이기 때문이다. 이 책을 읽는 것 만으로도 배울 수 있는 관련지식과 경험의 규모는 엄청나다. 아직도 안 본 J2EE개발자가 있다면 얼른 구해서 읽으시길.</p> <p>문제많은 EJB. 그러나 EJB에서 배울 것은 많다. EJB에는 우리가 취해야 할 좋은 점들이 충분히 있다. 또 교훈으로 삼아 피해야 할 나쁜 점도 많다. EJB의 특징과 그 역사, 평가와 대안등을 살펴보는 것은 매우 의미 있는 작업이다.</p> <p><b>1. EJB와 컴포넌트 기술의 발전</b></p> <p>EJB의 처음 목적은 엔터프라이즈급의 개발을 간편하게 하도록 하는 것이었다. 그것은 EJB1.0의 스펙을 살펴보면 잘 알 수 있다. EJB의 설계자들은 개발자들이 트랜잭션, 상태관리, 멀티쓰레딩, 리소스풀링이나 복잡한 로우레벨의 API와 같은 시스템적인 부분에 대해서 많은 신경을 쓰지 않고 개발 대상 도메인과 비즈니스로직에 집중할 수 있도록 하려는 것이었다. 또 한가지 강조한 부분은 EJB는 Java의 캐치프레이즈 그대로 한번 만들어지면 어떠한 다른 플랫폼과 서버환경에서도 재컴파일이나 소스코드 변경없이 사용하도록 하려는 것이었다.</p> <p>EJB가 처음 등장했던 1998년에 당시 엔터프라이즈 컴포넌트 기술은 MS의 MTS와 CORBA정도가 주류로 존재했었다. COM/DCOM기술에 기반을 둔 MTS의 MS에 대한 의존성의 한계와 너무 방대한 스펙과 그에 따른 제약(CORBA는 진정한 애플리케이션 서버 기술로는 볼 수 없다)으로 역시 크게 쓰이지 못하고 있던 CORBA가 일반 개발자의 별다른 주목을 받지 못하고 있던 상황에서 EJB는 Java기반의 매우 열린기술과 이상적이고 간결해 보이는 스펙등으로 사람들의 관심을 끌기 시작했다. 하지만 그때는 아직 Java기술자체가 계속 발전하던 시기였고 EJB의 등장 이후에 Java는 언어적인 면에서 지속적으로 큰 변화들을 가져왔다. 하지만 EJB는 그 초기 등장이후 로컬인터페이스를 가진 EJB2.x에서 일부 최적화가 있었을 뿐 초기의 설계에서 근본적인 변화가 없이 현재에 이르고 있다. EJB가 초기의 기술에서 크게 변화하지 못하고 정체되어 있는 사이에 새로운 개념과 열린구조를 가진 .NET이나 Web Service같은 새로운 기술들이 등장했고 언어자체로 자바도 많은 발전이 있었다. </p> <p>EJB는 그 스펙의 발전과정에서 여러가지 논쟁들을 가져왔는데 제일 문제가 되었던 부분은 EJB가 컴포넌트 기술과 리모팅 기술을 구분없이 혼재해서 가지고 있다는 점이다. 덕분에 EJB는 리모팅 부분의 다양한 기술을 적용할 수 없는 유연하지 못한 구조일 수 밖에 없었다. 또한 EJB를 오브젝트관점에서 봐야 하는지 컴포넌트로 이해해야 하는지에 대한 부분도 스펙의 발전에서 계속 고민되어진 부분이다. 특정 컴포넌트 기술에 종속적이지 않은 lightwegith container와 같은 오브젝트 기반의 기술도 컴포넌트들이 갖는 많은 특징들과 장점을 가지고 있음은 분명한 사실이다. 또 엄밀히 컴포넌트 기반의 소프트웨어 기술과 오브젝트 기반의 기술을 구분하는 것은 간단한 문제는 아니라고 생각된다.</p> <p>EJB의 등장과 함께 기대했던 것은 EJB컴포넌트마켓의 발전이다. EJB기반의 다양한 3rd-party 컴포넌트들이 개발되고 또 이런 컴포넌트들을assemble해서 사용할 수 있다는 것이 EJB기술 마케팅의 주요한 포인트 중의 하나였음이 분명하다. 하지만 그 결과는 매우 실망스럽다. EJB컴포넌트 시장은 거의 존재한 적이 없다고 할 수 있을 정도로 미미한 수준이었다. 이는 부분적으로 EJB기술자체의 한계에도 기인하지만 한편으로는 엔터프라이즈 레벨의 기능들이 컴포넌트라는 것으로 만들어져 사용되어질 수 있기에는 너무 복잡하고 너무 특정 설계에 의존적인 것이 주요한 원인이라고 볼 수 있다. 그나마 활발한 컴포넌트 시장이 존재한다고 하는 ActiveX/.NET컴포넌트 시장에도 거의 대부분은 UI기능을 지원하는 컴포넌트만이 명맥을 유지하고 있을 뿐이지 본격적인 엔터프라이즈급의 컴포넌트는 찾아보기 힘들다는 점을 생각해보면 EJB의 컴포넌트 시장에 대한 나이브한 기대 자체에 문제가 있었다고 볼 수 있다.</p> <p>최근 몇년 사이에 일어난 AOP에 대한 관심과 기술의 발전은 EJB가 가지는 많은 특징들을 좀 더 일반적인 방법으로 대치할 수 있는 가능성을 열어주었다. Interception이라는 관점에서 EJB서비스의 핵심적인 요소들은 AOP를 통해서 쉽게 구현가능해졌다. AOP는 OOP가 가지는 장점을 극대화하면서 이를 더욱 보완할 수 있는 기술임에 틀림이 없다. AOP를 통해서 제시되는 많은 기능들은 사실 EJB를 통해서 그동안 지속적으로 적용되어져 왔던 것이다. 다만 EJB에서는 매우 복잡한 방법과 구조를 통해서 이루어 졌다면 AOP는 그부분을 매우 심플한 방법과 새로운 자바자체의 기술들을 통해서 쉽게 적용할 수 있는 길을 열어준 것이다.</p> <p><b>2. 우리가  EJB에서 원하는 것</b></p> <p>EJB를 사용한다는 많은 프로젝트에서 사실 SLSB만을 사용하는 경우가 많다. SFSB은 사용빈도가 매우 적다. State를 Business Service Layer에서 관리한 다는 것 자체가 문제이다. 상태정보를 관리하기엔 SFSB보다 HTTP session이 훨씬 더 편하기 때문이다. Entity Bean은 가장 많이 외면된 EJB의 기능중의 하나이다. J2EE진영에서 조차 Entity Bean에 대한 비판은 끊임없이 이어져왔다. Entity Bean을 실전에서 적용해본 개발자 중에서 만족한 사람은 거의 없다고 보인다. 근본적인 EJB의 모든 문제점을 모두 가지고 있는데다 CMP/BMP은 지속적인 스펙발전에도 불구하고 현실적인 문제를 제대로 반영해 줄 수 없는 심각한 한계를 가진 persistence 기술이기 때문이다. JDO나 Hibernate, TopLink등의 제대로 현실 문제를 반영할 수 있는 O/R매핑기술이 널리 적용되기까지 O/R 매핑기술에 대한 부정적인 인식을 만들어온 주범이라고 볼 수 있다.</p> <p>결국 개발자들에 의해서 선택되어진 것은 SLSB와 MDB정도이다. 최근에 EJB프로젝트에서 주로 사용되어지는 것은 Local Interface기반의 SLSB일 것이다. 결국 EJB는 결국 실제 필요보다 너무 많은 기술을 가지고 있고 필요없이 복잡하다고 할 수 있겠다.</p> <p>SLSB가 가지고 있는 기능들을 뽑아보자면 선언적 트랜잭션 관리, 리모팅, 클러스터링, 쓰레드관리, 인스턴스 풀링, 리소스 관리, 보안, 비즈니스 오브젝트 관리 정도로 정리될 수 있다.</p> <p>1) CMT<br />
 CMT(container-managed transaction)은 EJB의 가장 중요한 기능중의 하나라고 볼 수 있다. 자바코드에서 트랜잭션에 관한 부분을 선언적으로 쓸 수 있게 분리해냈다는 것은 매우 의미있는 것이다. 물론 복잡한 비즈니스로직을 가지는 경우 CMT만으로는 불가능 한 경우가 있기는 하지만 CMT는 그 자체로 매우 가치있는 기능이며 EJB를 사용하게 하는 주요한 이유중의 하나로 볼 수 있다. 하지만 대부분의 시스템구성이 단일DB(그 안에서 다시 clustering을 사용하는 경우를 포함하여)라고 볼 때 애플리케이션 서버 전체적으로 적용되는 JTA기반의 트랜잭션 관리는 대부분의 경우 구지 필요없는 부담이다.</p> <p>Spring의 AOP기반의 선언적 트랜잭션관리 기능은 복잡하게는 멀티DB기반의 환경을 위한 JTA이용으로부터 단순하게는 JDBC API레벨까지 상황에 맞게 scale up/down이 가능하도록 설계되어 있다. 또한 checked exception에서의 rollback rule을 쉽게 설정하도록 할 수 있고 복잡한 트랜잭션의 경우 JTA보다 심플한 방법으로 프로그램에서 트랙잭션을 관리할 수 있는 방법을 제공한다.</p> <p>2) Remoting<br />
 리모팅과 컴포넌트 이 두가지를 구분하지 않고 혼재해놓은 것이 EJB의 대표적인 문제점의 하나로 볼 수 있다. 대부분의 경우는 리모팅을 필요로하지 않는데다 리모팅을 해야 하는 경우 이부분이 독립적으로 삽입되어져 사용되어질 수 없는 고정적인 구조(EJB2.1에 들어서 비로서 RMI/IIOP에 더불어 web service remoting이 지원되어졌다)를 가지고 있기 때문이다. 이미 언급했던 것처럼 대부분의 경우 co-located되어진 구조가 remote 기반의 구조보다 낫다. 그리고 웹서비스를 제공하기에는 EJB보다 더 나은 방법이 얼마든지 있다.</p> <p>3) Clustering<br />
 EJB의 확장성은 매우 편리하고 뛰어난 것으로 제시되어져 왔지만 사실 그렇지 않다. 뛰어난 클러스터링을 지원하는 EJB지원 WAS는 매우 고가인데다 Entity bean과 SFSB는 사실 클러스터링하기에는 너무 제한적이 많은 문제점을 가지고 있다. 결국 SLSB의 클러스터링이 남게 된다. SLSB의 클러스터링의 장점은 사실 제한적이며 성능이나 확장성 면에서 볼때 co-located된 구조가 더 많은 장점이 있다.</p> <p>4) Thread Management<br />
 EJB처럼 동시성의 문제 때문에 특정 메소드가 실행되고 있는 중에 전체 bean을 locking하는 방식은 적절하다고 볼 수 없다. 대신에 서블릿이나 Struts Action처럼 instance variable을 가지고 있지 않은 싱글 오브젝트를 이용한다면 복잡한 쓰레드관리를 해야 할 필요가 없다. 또는 각각의 request에 대해서 새로운 인스턴스를 만들어서 쓰는 것도 간편하게 동시성 문제를 해결 할 수 있다. 최신 JVM은 사실 간단한 오브젝트 생성과 삭제에 별 부담을 가지지 않는다. WebWork/XWork이나 Hibernate에서 왜 의도적으로 오브젝트 풀링을 사용하지 않고 있는지 살펴 볼 필요가 있다. 아니면 자바언어의 synchronization 기능이나 concurrency api등을 이용해서 오브젝트를 작성할 수도 있다. </p> <p>5) Instance Pooling<br />
 EJB인스턴스 풀링은 EJB가 처음 만들어지던 Java 1.1시절에는 garbage collection상의 문제를 피하기 위한 것과 메모리 절약이라는 측면에서 가치가 있었다. 하지만 GC기술이 충분히 발달했고 메모리가격이 매우 저렴한 지금은 그만한 가치가 없다. 오히려 적절한 instance pool 사이즈와 쓰레드 사이즈를 어떻게 결정해야 하는가하는 난감한만 남아 있을 뿐이다.</p> <p>6) Resource Pooling<br />
 DB커넥션과 같은 리소스 풀링은 EJB의 인스턴스 풀링보다 어쩌면 더 중요하다. 하지만 리소스 풀링은 EJB의 기술이 아니라 J2EE애플리케이션 서버 또는 서블릿 컨테이너 레벨에서 준비되어진 기술이다. 따라서 EJB와 상관없이 얼마든지 사용되어 질 수 있다.</p> <p>7) Security<br />
 CMT와 더불어 EJB의 선언적 프로그래밍 기능으로 주목받은 것이 바로 보안에 관한 부분이다. 그러나 대부분의 복잡한 보안요구사항들은 EJB가 지원하는 선언적 보안방식으로는 구현하기가 불가능하다. 또한 선언적인 보안설정등은 서블릿컨테이너 레벨에서도 사용가능하다. Spring에서는 AOP와 interceptor chain등을 이용해서 쉽게 복잡한 보안프레임웍을 구성할 수 있게 해준다. </p> <p>8) Business Object Management<br />
 EJB의 장점중의 하나는 개발자로 하여금 인터페이스기반의 프로그래밍을 강제하고 있다는 점이다. 인터페이스와 구현의 분리는 좋은 프로그래밍 방식이다. 하지만 EJB만 그런 분리를 지원하는 것이 아니다. 자바언어 자체에서 이미 훌륭하게 인터페이스를 지원하고 있으며 lightweight container도 자체적으로 관리하는 오브젝트에 대해서 인터페이스를 통한 접근을 유용하게 해주는 Factory역할을 해준다. 또 IoC기능의 지원을 통해서 fine-grained된 오브젝트의 의존구조를 컨테이너 레벨에서 관리함으로 매우 심플한 프로그래밍 모델을 제공하고 있다.</p> <p>우리는 EJB의 여러 장점들에 대해서 부인할 필요는 없다. 동시에 그것들이 EJB를 통해서만 지원되는 것이 아님을 알아야 하며 좀더 심플하고 바람직한 방법을 추구해야 할 것이다. </p> <p><b>3. 우리가  EJB로부터 원하지 않는 것</b></p> <p>참으로 많다. 다 적기도 귀찮다. 한마디로 요약해서 말하자면 “심플하게 할 수 있는 것을 복잡하게 하게 하는 것”이라고 할 수 있다. </p> <p><b>4.  EJB는 나아질 수 있는가?</b></p> <p>EJB 3.0이 최근 자바진영의 주된 화제중의 하나이다. 그간의 복잡성을 최대한 배제하고 대폭적으로 심플한 구조와 방법을 채택하겠다는 것이 EJB 3.0 전문가 그룹의 의지이다. 상당히 고무적이다. 하지만 EJB 3.0을 기대하는 것에는 한계가 있다. 시기적으로 제대로 EJB 3.0을 사용하게 될 수 있는 시점은 2006이나 되야 가능 할 것으로 보인다. 또 WAS업체의 마케팅관점에서 간섭을 무시할 수 없다. 복잡해야 비싸게 팔아먹을 수 있다고! </p> <p> 아무래도 계속 지적되었던 EJB문제들에 대한 모든 면에서의 변화를 기대하기는 힘들 것 같다.</p> <p><b>5. 미신과 오해들</b></p> <p>몇가지 흔한 잘못된 오해들을 꼽아보자.<br />
 1) J2EE == EJB?<br />
 J2EE는 EJB 이상이고 EJB는 자바의 일부일 뿐이다. EJB를 포기하는 것이 J2EE를 버리라는 것은 절대 아니다. </p> <p>2) 모든 개발자들은 EJB를 이해하고 있다.<br />
 640페이지에 달하는 EJB2.1 스펙을 한번이나 다 읽어보기라도 한 사람이 얼마나 될까? 나도 관심있는 주제를 중심으로 훑어만 봤을 뿐이다. EJB와 그 관련기술에 대한 깊은 이해와 지식을 가진 개발자와 아키텍트는 극히 소수이다. 사실 다 이해하기에 너무 복잡하다. 샘플 코드 배끼기 수준의 EJB개발자가 얼마나 많은가?</p> <p>3) MDB없이는 asynchronous application개발을 할 수 없다.<br />
 MDB의 상당부분은 EJB가 아니라 J2EE에 기반하고 있다. </p> <p>4) EJB없는 심플한 시스템을 만들 수는 있으나 그것은 확장성이 없다.<br />
 구지 설명할 필요조차 없는 생각이다.</p> <p><b>6. 그럼 대안은?</b></p> <p>이 책이 이야기 하고 있는 핵심은 EJB를 사용하지 않고 엔터프라이즈 레벨의 서비스를 더 심플하고 생산적인 방법으로 사용할 수 있는 방법에 관한 것이다. 그 평가와 상관없이 EJB는 여전히 그 세력이 막강하다. 엄청난 규모의 WAS제작업체의 파워와 마케팅 능력, 언론플레이는 아직도 대부분의 기업의 의사결정을 담당하는 사람들에게 막대한 영향력을 미치고 있다. 또 많은 개발자들이 아직 EJB외의 대안에 대해서 잘 모르고 안다하더라고 막연한 거부감이나 부담감을 가지고 있는 것이 현실이다. 시간이 점점 지나고 Spring과 같은 좋은 대안들이 현실에서 검증되고 지속적으로 인정받기 시작하면서 EJB는 점점 그 주권을 내주지 않을까 기대해본다. </p> <p>EJB를 배제한 J2EE시대를 이끌어 나갈 수 있을 것으로 주목받고 있는 기술들을 꼽아 본다면.<br />
 - Spring Framework : 두말할 것 없는 가장 주목받고 있는 EJB이상의 뛰어난 프레임웍. 이 책의 결론이자 검증가능한 증거일 것이다.<br />
 - Nanning Aspect : AOP기반의 솔루션.<br />
 - JBoss 4 : AOP를 통한 POJO기반의 엔터프라이즈 서비스를 이용할 수 있다.<br />
 - PicoContainer : Spring과 유사한 IoC기반의 Lightweight container.<br />
 - Hibernate : POJO기반의 최고의 O/R매핑 솔루션<br />
 - JDO : EJB를 대신할 수 있는 뛰어난 퍼시스턴스 기술의 하나<br />
 - HiveMind : 또하나의 IoC컨테이너.<br />
 - iBatis : 심플한 data access와 transaction방법을 제공<br />
 - GLUE : 뛰어난 성능의 lightweight 웹 서비스 리모팅 솔루션</p> 이런 기술들은 물론 SUN의 J2EE표준이 아니다. 그러나 표준만 써야 할 것인가? J2EE의 표준화 과정의 문제점은 너무나도 많다. 항상 표준만이 옳고 최선의 것이 아니다. 이미 EJB의 발전과정을 통해서 그 문제점에 대해서는 충분히 경험했다. 많은 필드의 개발자들이 만족하고 사용하고 퍼뜨리고 함께하는 것 그것이 진정한 의미의 표준이 아닐까 생각한다.			 ]]> 
		</description>
		<category>Task</category>

		<comments>http://namkee.egloos.com/3082415#comments</comments>
		<pubDate>Thu, 08 Feb 2007 04:58:55 GMT</pubDate>
		<dc:creator>namkee</dc:creator>
	</item>
	<item>
		<title><![CDATA[ Spring Framework 개요 - IOC, AOP ]]> </title>
		<link>http://namkee.egloos.com/3081818</link>
		<guid>http://namkee.egloos.com/3081818</guid>
		<description>
			<![CDATA[ 
  <div class="post-sub ptl"><img height="17" alt="출처" src="http://blogimgs.naver.com/blog20/blog/ico_origin.gif" width="32" /> <a class="link1" href="http://blog.naver.com/pnh97121" target="_top">블로그 &gt; 나를 찾아서</a><br />
<img height="17" alt="원본" src="http://blogimgs.naver.com/blog20/blog/ico_source.gif" width="32" /> <a class="link1" href="http://blog.naver.com/pnh97121/80012609395" target="_top">http://blog.naver.com/pnh97121/80012609395</a></div><div class="post-view pcol2"><!-- 포스팅 --><strong><br />
스프링 프레임워크 개요</strong> <br />
스프링은 그 이름 자체로도 많은 의미를 내포하고 있다. 봄! 이 얼마나 설레는 단어인가? 봄이라는 이름만으로도 무거운 J2EE의 사용으로 지친 개발자들에게 이제 겨울이 끝나고 새로운 계절이 돌아오고 있음을 함축적으로 표현해내고 있다. 스프링은 로드 존슨이 쓴 「Expert one-on-one J2EE Design and Development」란 책에서 소개된 소스코드를 기반으로 2003년 2월 오픈소스로 시작된 프로젝트이다. 스프링이 추구하는 바는 크게 두 가지이다. <br />
<br />
[1] 복잡하고 무거운 J2EE 기술의 사용을 쉽고 가볍게 만들어주고, 자연스럽게 검증된 최상의 실천 사례들을 구현하도록 함으로써 좋은 프로그램이 작성될 수 있도록 유도한다. <br />
<br />
[2] 기존의 잘 알려진 기술들을 프레임워크 내에서 일관된 방법으로 쉽게 사용할 수 있도록 돕는다. <br />
<br />
이를 위해 스프링은 다른 프레임워크와는 차별화된 다음과 같은 특징을 가진다. <br />
<br />
◆ 스프링은 EJB를 사용하건 하지 않건 관계없이 비즈니스 객체들을 효과적으로 구성하고, 관리하는 방법을 제공하는 데 초점을 맞춘다. <br />
<br />
◆ 스프링은 계층화된 아키텍처를 갖고 있으며, 그 중 어떤 부분도 독립적으로 사용될 수 있도록 모듈화되어 있다. 뿐만 아니라 각각의 모듈은 일관된 방법으로 사용할 수 있기 때문에 한번 익숙해지고 나면 사용이 무척 쉽다. <br />
<br />
◆ 스프링은 전체 프로젝트의 설정을 관리할 수 있는 일관된 방법을 제공함으로써, 개발자들이 각종 프로퍼티 파일을 작성하지 않도록 유도한다. 이것은 IoC라는 스프링의 특징 때문인데, 객체들간의 의존성이 따로 관리됨으로써 비즈니스 로직이 EJB로 개발되었건 일반 자바 객체로 개발되었건 동일한 방법으로 해당 로직을 이용할 수 있는 이점도 추가된다. <br />
<br />
◆ 스프링 기반으로 작성된 애플리케이션은 스프링의 API에 의존하지 않는다. 이것은 어떤 애플리케이션 서버와도 쉽게 연동되도록 하며, 심지어 스프링을 사용하지 않았을 때조차도 비즈니스 로직의 재사용이 가능해지는 요인이 된다. <br />
<br />
◆ 스프링은 AOP 지원을 통해 주요 비즈니스 로직과 시스템 전반에 걸친 기능 모듈을 완벽히 분리해내도록 도와준다. <br />
<br />
◆ 스프링은 작성된 코드에 대한 유닛 테스트를 쉽게 할 수 있도록 도와준다. <br />
<br />
<span style="COLOR: #2e3192">스프링의 기능과 사용 시나리오</span> <br />
현재 스프링은 1.0 버전이 출시된 상태이다. 스프링 홈페이지(<a class="con_link" href="http://www.springframework.org/" target="_blank"><u><span style="COLOR: #0000ff">www.springframework.org</span></u></a>)에서 spring-framework-1.0.2-with-dependencies.zip 파일을 다운받기 바란다. 이 파일은 의존성 있는 관련 라이브러리가 모두 포함된 버전이다. 스프링의 전체 기능은 크게 7개의 모듈로 구성된다(&lt;표 1&gt;). <br />
<!-- 큰 이미지 하나 중간에 놓을때  사용하는 소스입니다. --><br />
<center><table width="420"><tbody><tr><td align="middle"><img src="http://www.zdnet.co.kr/images/stories/etc/2004/_12/1221-2/pic02.jpg" /></td></tr><tr><td class="bk" align="middle"><span style="FONT-FAMILY: 돋움">&lt;그림 2&gt; 스프링의 기능 요소</span></td></tr></tbody></table></center><br />
<!-- 큰 이미지 하나 중간에 놓을때  사용하는 소스입니다. --><br />
<center><table width="420"><tbody><tr><td align="middle"><img src="http://www.zdnet.co.kr/images/stories/etc/2004/_12/1221-2/p1.jpg" /></td></tr><tr><td class="bk" align="middle"><span style="FONT-FAMILY: 돋움">&lt;표 1&gt; 스프링의 기능 요소</span></td></tr></tbody></table></center><br />
스프링 배포 파일의 압축을 풀면 dist란 디렉토리가 나타난다. 그 안에 있는 spring.jar가 앞에서 언급한 스프링의 모든 기능을 포함하는 파일이다. 각각의 기능 중 필요한 부분을 따로 사용할 경우를 위해 패키지별로 묶은 별도의 JAR 파일이 함께 제공된다. <br />
<br />
스프링을 이용한 일반적인 형태의 웹 애플리케이션은 &lt;그림 3&gt;과 같은 구조를 가진다. 톰캣, 웹로직, 웹스피어, JBoss를 포함한 어떤 웹 애플리케이션 서버에서도 동작된다. IoC 컨테이너의 핵심인 Core 패키지와 AOP 지원을 위한 AOP 패키지, 기능을 구현한 빈 객체에 대한 접근을 제공하는 Context 패키지는 반드시 포함되어야 한다. 대부분 데이터베이스 처리를 수행하기 때문에 DAO 패키지도 일반적으로 포함된다. <br />
<br />
스프링 애플리케이션은 일반적으로 ORM 솔루션을 채택하고, 특히 하이버네이트와 궁합이 잘 맞기 때문에 하이버네이트를 설치하고 ORM 패키지를 이용하는 경우가 일반적이다. 그 위에서 Web 패키지를 기반으로 Web MVC 패키지를 이용해서 애플리케이션을 개발한다. <br />
<!-- 큰 이미지 하나 중간에 놓을때  사용하는 소스입니다. --><br />
<center><table width="420"><tbody><tr><td align="middle"><img src="http://www.zdnet.co.kr/images/stories/etc/2004/_12/1221-2/pic03.jpg" /></td></tr><tr><td class="bk" align="middle"><span style="FONT-FAMILY: 돋움">&lt;그림 3&gt; 시나리오 1. 완전한 형태의 스프링 웹 애플리케이션</span></td></tr></tbody></table></center><br />
만일 스프링의 Web MVC 패키지를 이용하지 않고, 스트럿츠나 웹워크를 제어 계층에 사용하고 싶다면 Web MVC를 스트럿츠가 대체하는 &lt;그림 4&gt; 외에 같은 구조로 웹 애플리케이션이 개발될 것이다. <br />
<!-- 큰 이미지 하나 중간에 놓을때  사용하는 소스입니다. --><br />
<center><table width="420"><tbody><tr><td align="middle"><img src="http://www.zdnet.co.kr/images/stories/etc/2004/_12/1221-2/pic04.jpg" /></td></tr><tr><td class="bk" align="middle"><span style="FONT-FAMILY: 돋움">&lt;그림 4&gt; 시나리오 2. 서드파티 WAF와 ORM을 연계한 웹 애플리케이션</span></td></tr></tbody></table></center><br />
이 밖에도 EJB를 사용하는 경우 AbstractEnterpriseBean이라는 POJO를 이용해서 EJB를 스프링에서 관리하도록 하고, SlsbInvoker를 이용해서 EJB에 대한 접근 경로를 제공하는 EJB 사용 유형이 있다. 또한 웹 서비스를 포함한 다른 애플리케이션과 연동하는 경우를 위해 Remote 패키지가 제공되기도 한다. <br />
<br />
스프링은 그 자체로도 한 권의 책을 쓸 수 있을 만큼 방대한 기술이다. 그 모두를 짧은 연재를 통해 소개한다는 것은 불가능하다. 그러한 이유로 스프링에 대한 소개는 이쯤에서 마무리하고, 스프링을 이해하기 위해 반드시 알아야 하는 IoC(Inversion of Control) 컨테이너의 개념과 AOP(Aspect Oriented Programming)를 간단히 설명하고, 2개의 작은 예제를 소개하는 것으로 이번 글을 마무리하겠다. 부족한 설명은 필자들이 운영하는 <a class="con_link" href="http://java.techedu.net/phpBB2" target="_blank"><u><span style="COLOR: #0000ff">VSSH 포럼</span></u></a>이나, 스프링 관련 기사 및 자료들을 정리한 <a class="con_link" href="http://java.techedu.net/phpBB2/viewtopic.php?t=117" target="_blank"><u><span style="COLOR: #0000ff">리소스 맵</span></u></a>을 통해 여러분 스스로 익혀나가기를 바란다. <br />
<br />
<b>IoC 컨테이너와 AOP</b> <br />
스프링은 다른 프로젝트에서 개발된 컴포넌트를 조립해서 응집력 있는 애플리케이션의 개발이 가능하도록 도와주는 IoC 컨테이너이며, 다른 말로 경량급 컨테이너(Lightweight Container)라고도 한다. IoC 컨테이너의 또 다른 종류로는 PicoContainer와 아파치의 아발론, 그리고 HiveMind 등이 있다. <br />
<br />
그 중에서 현재 가장 널리 사용되고 있는 것은 스프링과 PicoContainer이다. IoC 컨테이너는 다른 컨테이너와 달리 애플리케이션 코드와 컨테이너간의 의존성을 최소화하는 것이 특징이다. <br />
<br />
IoC 컨테이너가 컨테이너에 대한 의존성을 최소화하면서 컴포넌트를 엮어주는 일을 수행하는 밑바탕에는 제어 역행화(Inversion of Control)라는 개념이 깔려 있다. 제어 역행화는 리팩토링의 저자이기도 한 <a class="con_link" href="http://martinfowler.com/articles/injection.html" target="_blank"><u><span style="COLOR: #0000ff">마틴 파울러의 홈페이지</span></u></a>에 잘 정의되어 있다. <br />
<br />
제어 역행화라는 용어는 직관적이지 못하기 때문에, 또 다른 말로 연관성 삽입(Dependency Injection)이라고도 불려진다. 연관성 삽입 패턴은 컴포넌트의 설정을 그것의 사용에서 분리해야 한다는 원칙(The principle of separating configuration from use)에서 출발한다. 그러한 원칙을 위한 또 다른 사례는 J2EE 패턴 중 서비스 로케이터(Service Locator) 패턴이다. <br />
<br />
의존성 삽입 패턴을 이해하기 위해 간단한 예를 하나 살펴보도록 하자. 어느 특정 감독이 만든 영화를 검색해서 그 결과를 전달해주는 컴포넌트를 사용하는 것이다. 코드에서 보여지는 findAll()이라는 메쏘드를 가지는 finder 객체가 필요하단 사실을 알 수 있다. <br />
<br />
일반적으로 이럴 때 기능 확장을 위해 MovieFinder와 같은 인터페이스를 작성하게 된다. <br />
<div style="MARGIN-LEFT: 15px"><br />
public interface MovieFinder { <br />
&nbsp;&nbsp;&nbsp;&nbsp;List findAll(); <br />
} <br />
</div><br />
영화 정보가 콜론으로 구분된 CSV 파일에 기록되어 있다면, MovieFinder 인터페이스를 구현한 ColonDelimitedMovieFinder 클래스가 필요할 것이다. 또한 그 정보는 MovieLister에 생성자를 이용해서 초기화될 것이다. <br />
<div style="MARGIN-LEFT: 15px"><br />
class MovieLister... <br />
&nbsp;&nbsp;&nbsp;&nbsp;private MovieFinder finder; <br />
&nbsp;&nbsp;&nbsp;&nbsp;public MovieLister() { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;finder = new ColonDelimitedMovieFinder("movies1.txt"); <br />
&nbsp;&nbsp;&nbsp;&nbsp;} <br />
</div><br />
전체적인 시스템 구조는 &lt;그림 5&gt;와 같은 형태이다. MovieLister 클래스는 MovieFinder 인터페이스 정보만을 이용해서 기능을 구현할 수 있지만, 해당 기능을 사용하기 위해 MovieFinderImpl 클래스 중에서 ColonDelimitedMovieFinder를 이용한다는 구체적인 설정 정보가 클래스의 코드에 포함되어 있다. 이것은 데이터가 DB나 XML로 변경되어 RDBMovieFinder나 XMLMovieFinder로 교체될 경우 코드를 수정해서 다시 빌드해야 한다는 사실을 의미한다. <br />
<!-- 큰 이미지 하나 중간에 놓을때  사용하는 소스입니다. --><br />
<center><table width="420"><tbody><tr><td align="middle"><img src="http://www.zdnet.co.kr/images/stories/etc/2004/_12/1221-2/pic05.jpg" /></td></tr><tr><td class="bk" align="middle"><span style="FONT-FAMILY: 돋움">&lt;그림 5&gt; 일반적인 제어 흐름을 통한 의존성 표현</span></td></tr></tbody></table></center><br />
사실 MovieLister는 정보가 CSV 파일에 기록되어 있건, DB에 기록되건, XML에 기록되건 영향을 받지 않아야 정상이라고 할 수 있다. 어떻게 하면 이처럼 불필요한 의존 관계를 없앨 수 있는 것일까? <br />
<!-- 큰 이미지 하나 중간에 놓을때  사용하는 소스입니다. --><br />
<center><table width="420"><tbody><tr><td align="middle"><img src="http://www.zdnet.co.kr/images/stories/etc/2004/_12/1221-2/pic06.jpg" /></td></tr><tr><td class="bk" align="middle"><span style="FONT-FAMILY: 돋움">&lt;그림 6&gt; 제어역행화 패턴을 통한 의존성 삽입</span></td></tr></tbody></table></center><br />
그 해답은 설정 정보에 따라 어떤 구현 객체를 사용할 것인지를 결정하는 어셈블러를 이용해서 &lt;그림 6&gt;에서 보여지는 구조로 애플리케이션을 개발하는 것이다. <br />
<br />
MovieLister 클래스에서 선언된 MovieFinder 타입의 finder를 초기화하는 방법은 크게 2가지가 있다. 첫 번째는 생성자를 통해 속성을 초기화하는 것이고, 두 번째는 setMovieFinder()와 같은 Setter 메쏘드를 이용하는 것이다. 이러한 설정을 자동화하는 어셈블러를 구현해 놓은 것이 바로 IoC 컨테이너이다. <br />
<br />
연관성 삽입은 크게 Constructor Injection, Setter Injection, Interface Injection의 3가지 유형을 가진다. Constructor Injection이 생성자를 이용해서 의존성을 설정해주는 방법이고, Setter Injection이 Setter 메쏘드를 이용해서 의존성을 설정해주는 방법이다. Pico Container는 Constructor Injection을 주로 사용하고, 스프링은 자바 빈 규칙을 이용한 Setter Injection을 주로 사용한다. <br />
<br />
스프링의 IoC적인 특징은 AOP를 구현하는 핵심적인 원리가 되기도 한다. AOP는 아직 국내에는 생소한 분야이다. 김대곤님이 작성한 간단한 <a class="con_link" href="http://network.hanbitbook.co.kr/view.php?bi_id=968" target="_blank"><u><span style="COLOR: #0000ff">소개글</span></u></a>을 통해 AOP의 개념을 잡아보도록 하자. <br />
<br />
자금 이체를 하는 프로그램을 작성한다고 가정해 보자. 출금 계좌와 입금 계좌 그리고 이체 금액을 입력받아 SQL 문장 또는 함수 한 번 돌리는 것으로 모든 프로그래밍이 끝나는가? 그렇지 않다. 해킹을 방지하기 위해 사용자가 적절한 보안 프로그램을 설치했는지 점검하는 코드도 있어야 하고, 사용자가 인증되었는지 점검하는 코드도 써야 하고, 상대방 은행에서 적절하게 처리되었는지도 점점해야 하고, 혹시 사용자가 이체 버튼을 두 번 누른 것은 아닌가 체크해야 하고, 시스템 로그도 남겨야 한다. <br />
<br />
즉, 구현하려고 하는 기능 뿐 아니라 보안, 인증, 로그, 성능과 같은 다른 기능들도 녹아 있어야 한다는 뜻이다. 어쩌면 이체를 위한 코드보다 잡다한 다른 측면의 문제들을 다루는 코드가 더 길어질 수 있다. 이런 코드들은 입금이나 출금 같은 다른 곳에서도 공통적으로 사용되는 것이다. <br />
<!-- 큰 이미지 하나 중간에 놓을때  사용하는 소스입니다. --><br />
<center><table width="420"><tbody><tr><td align="middle"><img src="http://www.zdnet.co.kr/images/stories/etc/2004/_12/1221-2/pic07.jpg" /></td></tr><tr><td class="bk" align="middle"><span style="FONT-FAMILY: 돋움">&lt;그림 7&gt; AOP의 개념</span></td></tr></tbody></table></center><br />
구현하려고 하는 비즈니스 기능들을 AOP에서는 Primary(Core) Concern이라는 용어로 표현한다. 보안, 로그, 인증과 같이 시스템 전반적으로 산재된 기능들은 Cross-cutting concern이라고 부른다. AOP는 Cross-cutting concern을 어떻게 다룰 것인가에 대한 새로운 패러다임이라고 할 수 있다. <br />
<br />
그럼 AOP가 등장하기 이전에 우리는 어떻게 Cross-cutting Concern을 처리해왔을까? 매우 간단하다. Primary Concern를 구현한 프로그램에 함께 포함시켰다. Primary concern, Cross-cutting concern이 하나의 프로그램 안에 들어가게 되면, 프로그램을 이해하기가 힘들고, Cross-cutting concern 코드가 여기저기에 산재되어 수정하기 힘들게 된다. 당연히 생산성 떨어지고, 품질 떨어지고, 유지보수 비용은 많이 들게 된다. <br />
<br />
그럼 AOP는 Cross-cutting concern를 어떻게 처리하는가? AOP에서는 Primary Concern 구현하는 코드 따로, Cross-cutting concern 구현하는 코드도 따로 작성한다. 나중에 2개를 조합한 완벽한 애플리케이션이 만들어지는 것이다. <br />
<br />
AOP에서는 Cross-cutting concern 구현한 코드를 Advice라고 하며, Primary concern 구현한 코드를 Code라고 부른다. Code와 Advice를 연결해주는 설정 정보를 Point-cut이라고 하며, 둘을 조합해서 애플리케이션으로 완성하는 과정을 Weaving(조합)이라고 부른다. <br />
<br />
기술적 용어로서의 ‘Aspect’는 Advice와 Point-cut을 함께 지칭하는 단어이다. Point-cut은 어떤 Advice를 Code 어느 위치에 둘 것인가 하는 것이다. 스프링의 AOP 패키지는 이러한 AOP 개념을 구현한 것으로, 그 기반에는 설정을 이용으로부터 분리하는 의존성 삽입 패턴이 녹아 있다. <br />
<br />
<span style="COLOR: #2e3192">예제 1. 스프링의 WebMVC를 이해하자</span> <br />
이제 스프링을 이해하기 위해 2가지 예제를 살펴볼 것이다. 첫 번째 예제는 스프링 공식 홈페이지에 소개된 것으로 순수하게 스프링이 제공하는 기능만을 이용해서 개발된 <a class="con_link" href="http://www.springframework.org/docs/MVC-step-by-step/Spring-MVC-step-by-step.html" target="_blank"><u><span style="COLOR: #0000ff">예제</span></u></a>이다. <br />
<br />
국내에는 스프링과 관련한 자료가 전혀 없는 관계로 초보자들을 위해 이 예제를 편역하고 몇 가지 설명을 추가해 총 4부 8개의 강좌로 재구성해서 VSSH 포럼에 <a class="con_link" href="http://java.techedu.net/phpBB2/viewtopic.php?t=173" target="_blank"><u><span style="COLOR: #0000ff">등록</span></u></a>해 두었다. 자세한 설명을 원하는 독자는 관련 자료를 참고하기 바란다. <br />
<br />
여기서 소개하는 예제는 앞에서 소개한 강좌 중 2부까지 구현된 샘플이다. 예제를 실행해보기 위해서는 톰캣과 Ant, JDK 등이 설치되어 있어야 한다. 예제(springapp.zip)를 다운로드한 다음, 작업 디렉토리에서 압축을 풀면 build.properties 파일이 보일 것이다. <br />
<br />
해당 파일을 열어 배포될 경로와 톰캣 홈, 그리고 톰캣 관리자의 URL/아이디/패스워드 정보를 자신의 환경에 맞게 변경한다. 그런 다음 build와 deploy 타겟을 ant를 이용해서 순서대로 실행한다. 웹 브라우저를 이용해서 http://localhost:8080/springapp로 접속하면 아래와 같은 결과 화면을 볼 수 있을 것이다. <br />
<!-- 큰 이미지 하나 중간에 놓을때  사용하는 소스입니다. --><br />
<center><table width="420"><tbody><tr><td align="middle"><img src="http://www.zdnet.co.kr/images/stories/etc/2004/_12/1221-2/pic08.jpg" /></td></tr><tr><td class="bk" align="middle"><span style="FONT-FAMILY: 돋움">&lt;그림 8&gt; 스프링 WebMVC 예제화면</span></td></tr></tbody></table></center><br />
우선 예제의 web.xml 설정부터 살펴보도록 하자. DispatcherServlet이 springapp란 이름으로 등록되어 있고, htm으로 끝나는 모든 URL 패턴이 해당 서블릿으로 매핑되어 있다. DispatcherServlet은 스트럿츠의 ActionServlet의 기능과 유사한 일종의 FrontController 서블릿이다. <br />
<div style="MARGIN-LEFT: 15px"><br />
&lt;web-app&gt; <br />
&nbsp;&nbsp;&lt;servlet&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;servlet-name&gt;springapp&lt;/servlet-name&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;servlet-class&gt;org.springframework.web.servlet.DispatcherServlet&lt;/servlet-class&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;load-on-startup&gt;1&lt;/load-on-startup&gt; <br />
&nbsp;&nbsp;&lt;/servlet&gt; <br />
&nbsp;&nbsp;&lt;servlet-mapping&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;servlet-name&gt;springapp&lt;/servlet-name&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;url-pattern&gt;*.htm&lt;/url-pattern&gt; <br />
&nbsp;&nbsp;&lt;/servlet-mapping&gt; <br />
&lt;/web-app&gt; <br />
</div><br />
그렇다면 DispatcherServlet이 처리하는 제어 행위를 위한 struts-config.xml과 같은 설정 파일이 필요할 것이다. 스프링 MVC 패키지에서는 그 파일을 해당 서블릿 이름에 "-servlet.xml"을 붙여 작성하도록 권장하고 있다. 앞의 경우 서블릿의 이름을 springapp로 주었기 때문에 springapp-servlet.xml이 설정 파일이 되는 것이다. <br />
<br />
설정 파일을 보면, &lt;beans&gt;라는 루트 엘리먼트 밑에 &lt;bean&gt;이라는 설정이 반복되어 적용되고 있다. 이것이 스프링에서 BeanFactory를 이용해서 제공하고 있는 Setter Injection을 통해 설정과 그 사용을 분리하는 방법이다. <br />
<div style="MARGIN-LEFT: 15px"><br />
&lt;beans&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;bean id="springappController" class="web.SpringappController"&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property name="productManager"&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;ref bean="prodMan"/&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/property&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;/bean&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;bean id="prodMan" class="bus.ProductManager"&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property name="products"&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;list&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;ref bean="product1"/&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;ref bean="product2"/&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;ref bean="product3"/&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/list&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/property&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;/bean&gt; <br />
&lt;bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property name="mappings"&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;props&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;prop key="/hello.htm"&gt;springappController&lt;/prop&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/props&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/property&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;/bean&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;... (생략) ... <br />
&lt;/beans&gt; <br />
</div><br />
전체 애플리케이션의 동작 과정을 한번 살펴보자. <br />
<!-- 큰 이미지 하나 중간에 놓을때  사용하는 소스입니다. --><br />
<center><table width="420"><tbody><tr><td align="middle"><img src="http://www.zdnet.co.kr/images/stories/etc/2004/_12/1221-2/pic09.jpg" /></td></tr><tr><td class="bk" align="middle"><span style="FONT-FAMILY: 돋움">&lt;그림 9&gt; 스프링 WebMVC 예제동작 원리</span></td></tr></tbody></table></center><br />
웰컴 파일인 index.jsp에는 hello.htm에 대한 링크가 걸려있다. hello.htm에 대한 요청은 web.xml의 설정에 의해 springapp로 이름지어진 스프링의 web 패키지의 DispatcherServlet으로 전달된다. DispatcherServlet은 스프링의 core 패키지에 있는 BeanFactory를 이용해 IoC 컨테이너의 기본 원리에 따라 동작된다. 설정 파일인 springapp-servlet.xml을 통해 모든 의존성이 결정되어 제어가 반전되는 현상을 볼 수 있다. <br />
<!-- 큰 이미지 하나 중간에 놓을때  사용하는 소스입니다. --><br />
<center><table width="420"><tbody><tr><td align="middle"><img src="http://www.zdnet.co.kr/images/stories/etc/2004/_12/1221-2/pic10.jpg" /></td></tr><tr><td class="bk" align="middle"><span style="FONT-FAMILY: 돋움">&lt;그림 10&gt; VSSH 고객등록 예제화면</span></td></tr></tbody></table></center><br />
우선 &lt;prop key="/hello.htm"&gt;springappController&lt;/prop&gt;에 의해 hello.htm 요청을 SpringappController 클래스가 처리하게 되는데 그 사실을 DispatcherServlet은 전혀 모른다. SpringappController는 요청을 처리하는 과정에서 ProductManager의 구현을 필요로 하는데, 그게 어떤 클래스의 인스턴스인지를 본인은 모른다. 설정에 의해 자동적으로 bus.ProductManager가 결정되고, 해당 인스턴스가 거꾸로 SpringappController에 찾아와 연결된다. 이러한 제어의 반전이 스프링을 IoC(Inversion of Control) 컨테이너라고 부르게 하는 이유다. <br />
<br />
다음 코드는 스트럿츠의 액션과 유사한 역할을 수행하는 Controller 구현 샘플이다. ProductManager를 사용하고 있는데 신기하게도 setProductManager() 메쏘드만 있을 뿐, 인스턴스를 초기화하는 호출이 이루어지지 않는다. 스프링이 빈 설정을 참고해서 자동화하기 때문이다. handleRequest()의 결과로 ModelAndView가 리턴되어 넘어가는데, 이것은 스트럿츠의 ActionForward와 컨텍스트 정보를 합친 것으로 이해하면 되겠다. <br />
<div style="MARGIN-LEFT: 15px"><br />
public class SpringappController implements Controller { <br />
protected final Log logger = LogFactory.getLog(getClass()); <br />
&nbsp;&nbsp;&nbsp;&nbsp;private ProductManager prodMan; <br />
&nbsp;&nbsp;&nbsp;&nbsp;public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throws ServletException, IOException { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String now = (new java.util.Date()).toString(); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;logger.info("returning hello view with " + now); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Map myModel = new HashMap(); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;myModel.put("now", now); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;myModel.put("products", getProductManager().getProducts()); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return new ModelAndView("hello", "model", myModel); <br />
&nbsp;&nbsp;&nbsp;&nbsp;} <br />
&nbsp;&nbsp;&nbsp;&nbsp;public void setProductManager(ProductManager pm) { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;prodMan = pm; <br />
&nbsp;&nbsp;&nbsp;&nbsp;} <br />
&nbsp;&nbsp;&nbsp;&nbsp;public ProductManager getProductManager() { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return prodMan; <br />
&nbsp;&nbsp;&nbsp;&nbsp;} <br />
} <br />
</div><br />
<span style="COLOR: #2e3192">예제 2. 스프링과 스트럿츠, 하이버네이트를 통합한 예제</span> <br />
그럼 스프링을 기존의 스트럿츠 환경과 어떻게 연동할 수 있을까? 대표적인 ORM인 하이버네이트와는 어떻게 연동할 수 있을까? 이를 소개하기 위해 간단한 회원 관리 샘플을 개발했다. 이 예제는 벨로시티와 스트럿츠, 스프링, 하이버네이트를 통합하고자 하는 VSSH의 최종적인 모습을 보여주며, DBMS는 HSQLDB를 사용했다. <br />
<br />
예제 파일(vssh.zip)을 다운받아 자신의 작업 디렉토리에 압축을 풀고, was.properties 파일을 열어 자신의 운영 환경에 맞게 경로를 수정한다. 그런 다음, ant를 이용해서 makeDist, war-deploy 태스크를 순서대로 실행하면 빌드 및 배포 과정이 끝난다. 웹 브라우저를 이용해서 http://localhost:8080/vssh-b01에 접속하면 아래와 같은 결과 화면을 볼 수 있을 것이다. <br />
<br />
이 예제는 다음 강좌에서 다시 자세히 설명할 예정인데, 미리 상세한 내용을 알고 싶은 분은 LoveLazur의 <a class="con_link" href="http://eclipse.new21.org/phpBB2/viewtopic.php?t=401" target="_blank"><u><span style="COLOR: #0000ff">홈페이지</span></u></a>를 참고하기 바란다. 이번 예제부터는 복잡하기 때문에 이클립스와 같은 오픈소스 IDE를 이용하는 것이 좋다. <br />
<br />
스트럿츠와 스프링의 연동 방법은 각각을 이해하고 있다면 아주 간단히 처리된다. WEB-INF/lib 디렉토리에 각각의 라이브러리 JAR 파일을 추가한 다음, 스트럿츠 설정 파일인 struts-config.xml에 플러그인 설정만 하나 추가하면 되는 것이다. 플러그인으로 설정한 ContextLoader는 전달된 설정 파일을 이용해서 전체 애플리케이션 구성에 사용될 ApplicationContext를 구성하는 역할을 수행한다. <br />
<div style="MARGIN-LEFT: 15px"><br />
&lt;struts-config&gt; <br />
&lt;form-beans&gt; ... &lt;/form-beans&gt; <br />
&lt;action-mappings&gt; ... &lt;/action-mappings&gt; <br />
&lt;message-resources parameter="messages"/&gt; <br />
&lt;plug-in className="org.springframework.web.struts.ContextLoaderPlugIn"&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt;set-property property="contextConfigLocation" <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;value="/WEB-INF/applicationContext.xml, /WEB-INF/action-servlet.xml"/&gt; <br />
&lt;/plug-in&gt; <br />
&lt;/struts-config&gt; <br />
</div><br />
applicationContext.xml에는 애플리케이션 로직과 관련된 객체들을 앞서 설명한 빈 설정 방식으로 연동해서, 제어 역행화가 이루어지도록 하면 된다. <br />
<div style="MARGIN-LEFT: 15px"><br />
&lt;beans&gt; <br />
&lt;bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"&gt; <br />
&lt;property name="driverClassName"&gt;&lt;value&gt;org.hsqldb.jdbcDriver&lt;/value&gt; <br />
&lt;/property&gt; <br />
&lt;property name="url"&gt;&lt;value&gt;jdbc:hsqldb:data/vsshdb&lt;/value&gt;&lt;/property&gt; <br />
&lt;property name="username"&gt;&lt;value&gt;sa&lt;/value&gt;&lt;/property&gt; <br />
&lt;property name="password"&gt;&lt;value&gt;&lt;/value&gt;&lt;/property&gt; <br />
&lt;/bean&gt; <br />
&nbsp;&nbsp;&lt;!-- Hibernate SessionFactory --&gt; <br />
&lt;bean id="sessionFactory" class="org.springframework.orm.hibernate.LocalSessionFactoryBean"&gt; <br />
&lt;property name="dataSource"&gt;&lt;ref local="dataSource"/&gt;&lt;/property&gt; <br />
&lt;property name="mappingResources"&gt; <br />
&lt;list&gt;&lt;value&gt;model/Customer.hbm.xml&lt;/value&gt;&lt;/list&gt; <br />
&lt;/property&gt; <br />
&lt;property name="hibernateProperties"&gt; <br />
&lt;props&gt; <br />
&lt;prop key="hibernate.dialect"&gt;net.sf.hibernate.dialect.HSQLDialect&lt;/prop&gt; <br />
&lt;prop key="hibernate.hbm2ddl.auto"&gt;create&lt;/prop&gt; <br />
&lt;/props&gt; <br />
&lt;/property&gt; <br />
&lt;/bean&gt; <br />
&lt;!-- Transaction manager , can replace class Attribute ex.Transaction--&gt; <br />
&lt;bean id="transactionManager" class="org.springframework.orm.hibernate.HibernateTransactionManager"&gt; <br />
&lt;property name="sessionFactory"&gt;&lt;ref local="sessionFactory"/&gt;&lt;/property&gt; <br />
&lt;/bean&gt; <br />
&lt;bean id="customerDAO" class="dao.CustomerDAOImpl"&gt; <br />
&lt;property name="sessionFactory"&gt;&lt;ref local="sessionFactory"/&gt;&lt;/property&gt; <br />
&lt;/bean&gt;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&lt;/beans&gt; <br />
</div><br />
주의할 점은 모든 클래스에서 사용되는 객체 참조에서 항상 자바 빈 규칙에 따르는 setter()를 만들고, 직접 인스턴스를 초기화하지 않고 객체들의 의존성을 설정 파일에 적어줌으로써 스프링이 자동으로 의존성 관계를 삽입하도록 해야 한다는 것이다. <br />
<br />
다음의 CustomerAction을 살펴보면 ICustomerBizManager 타입의 cmgr이라는 인스턴스를 갖고 있는데, setCustomermanager()란 메쏘드만 있을 뿐 어디에도 초기화하는 루틴이 포함되어 있지 않다. 그런데도 cmgr.createCustomer()를 사용하고 있는 것을 볼 수 있다. <br />
<div style="MARGIN-LEFT: 15px"><br />
public class CustomerAction extends BaseAction { <br />
private ICustomerBizManager cmgr = null; <br />
public void setCustomerManager(ICustomerBizManager cmgr) { //def. <br />
this.cmgr = cmgr; <br />
} <br />
public ActionForward list(ActionMapping mapping, ActionForm form, <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HttpServletRequest request, HttpServletResponse response) <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throws Exception { <br />
request.setAttribute("custlist", cmgr.getCustomers()); <br />
return mapping.findForward("list"); <br />
} <br />
public ActionForward create(ActionMapping mapping, ActionForm form, <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HttpServletRequest request, HttpServletResponse response) <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throws Exception { <br />
DynaActionForm custForm = (DynaActionForm) form; <br />
cmgr.createCustomer((Customer) custForm.get("cust")); <br />
ActionMessages messages = new ActionMessages(); <br />
messages.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage( <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"cust.saved")); <br />
return list(mapping, form, request, response); <br />
} <br />
} <br />
</div><br />
이것은 action-servlet.xml과 applicationContext.xml에서 다음과 같은 설정이 되어 있으므로 그 정보에 따라 적절한 customerManager가 결정되기 때문에 가능해진다. <br />
<div style="MARGIN-LEFT: 15px"><br />
&lt;beans&gt; <br />
&lt;bean name="/cust" class="control.CustomerAction" singleton="false"&gt; <br />
&lt;property name="customerManager"&gt; <br />
&lt;ref bean="customerBizManager"/&gt; <br />
&lt;/property&gt; <br />
&lt;/bean&gt; <br />
&lt;bean id="customerBizManager" <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;class="org.springframework.transaction.interceptor. <br />
TransactionProxyFactoryBean"&gt; <br />
&lt;property name="transactionManager"&gt;&lt;ref local="transactionManager"/&gt;&lt;/property&gt; <br />
&lt;property name="target"&gt;&lt;ref local="customerBizManagerTarget"/&gt;&lt;/property&gt; <br />
&lt;property name="transactionAttributes"&gt; <br />
&lt;props&gt; <br />
&lt;prop key="create*"&gt;PROPAGATION_REQUIRED&lt;/prop&gt; <br />
&lt;prop key="update*"&gt;PROPAGATION_REQUIRED&lt;/prop&gt; <br />
&lt;prop key="delete*"&gt;PROPAGATION_REQUIRED&lt;/prop&gt; <br />
&lt;prop key="*"&gt;PROPAGATION_REQUIRED,readOnly&lt;/prop&gt; <br />
&lt;/props&gt; <br />
&lt;/property&gt; <br />
&lt;/bean&gt;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&lt;/beans&gt; <br />
</div><br />
<b>대안 기술에 대해 관심을 갖자</b> <br />
지금까지 스프링 프레임워크의 필요성을 설명하고, 기본 개념이라 할 수 있는 연관성 삽입 패턴과 AOP에 대해 간단히 살펴보았다. 또한 스프링의 특징과 스프링을 활용한 예제를 소개했다. 스프링이 아직 국내에 소개된 적이 없다보니 외국의 문서와 예제, 서적들을 뒤적거리면서 관련 자료를 정리하는데 한달이 넘는 시간이 소요되었다. <br />
<br />
하지만 아쉽게도 그동안 정리한 내용을 모두 소개하기에는 할당된 지면이 너무 부족해 꼭 필요한 부분만을 알려주는데 그친 듯하다. 설명이 미흡한 부분은 필자들의 VSSH 포럼을 활용하고, 궁금한 점이 있으면 언제든 질문해 주기 바란다. <br />
<br />
솔직히 말해 이 글을 쓰고 있는 필자도 여러분보다 몇 달 먼저 스프링을 공부한 정도의 수준밖에 되지 않는다. 미국, 일본, 중국, 독일 어디서나 스프링 관련 자료를 쉽게 구할 수 있었지만, 안타깝게도 국내에는 전혀 자료가 없었다. <br />
<br />
해외에서는 크게 주목을 받고 있는 스프링과 IoC 컨테이너에 대한 내용들이 왜 국내에서는 전혀 다루어지지 않고 있는지를 곰곰이 생각해본다. 우리네 개발자들은 촉박한 개발 일정에 쫓겨 신기술이나 대안 기술들을 공부할 만큼 다들 여유가 없는 것일까? 아니면 그러한 기술을 이미 익히고 있는 개발자들이 자신의 머리 속에 그 지식을 꼭꼭 숨겨두고 공개하지 않는 것일까? <br />
<br />
지금 자바 커뮤니티는 주류 기술의 버전 향상과 신기술의 출현 그리고 오픈소스 기반의 다양한 대안 기술의 등장으로 어느 때보다 급격한 기술 변화를 눈앞에 두고 있다. 아직 그러한 변화를 느끼지 못하고 있는 개발자라면 지금이 바로 그러한 변화에 대한 대비를 시작해야 할 때임을 깨달아야 한다. 또한, 그 과정에서 얻어진 노하우를 공유함으로써 더 큰 이익이 자신에게 돌아온다는 사실도 잊지 말기 바란다. @ <br />
<!-- 마소 저작권표시 --><br />
<span style="COLOR: #003399"><i>* 이 기사는 ZDNet Korea의 자매지인 <a class="con_link" href="http://www.imaso.co.kr/" target="_blank"><u><span style="COLOR: #0000ff">마이크로소프트웨어</span></u></a>에 게재된 내용입니다</i></span> <!-- //포스팅 --></div>			 ]]> 
		</description>
		<category>Task</category>

		<comments>http://namkee.egloos.com/3081818#comments</comments>
		<pubDate>Thu, 08 Feb 2007 01:36:32 GMT</pubDate>
		<dc:creator>namkee</dc:creator>
	</item>
	<item>
		<title><![CDATA[ Aspect Oriented Programming (AOP) ]]> </title>
		<link>http://namkee.egloos.com/3081769</link>
		<guid>http://namkee.egloos.com/3081769</guid>
		<description>
			<![CDATA[ 
  <b>저자:</b> 김대곤(private @ roadtohome.com)<br />
 <br />
 본 기사는 Aspect Oriented Programming에 대해 간략한 소개글이다. 아직까지는 생소한 분야일 수 있겠지만, 점점 더 많이 듣게 되리라 생각된다. AOP를 설명하는데 있어서 자주 등장하는 네 개의 용어들(<b>Aspect, Cross-cutting concern, Point-cut, Advice</b>) 를 설명함으로서 AOP가 왜 등장하게 되었으며, AOP가 제시하는 해결책에 대해 살펴볼 것이다. 먼저 "Aspect", "Oriented", "Programming"에서 생소한 단어는 단연 "Aspect"일 것이다. 야후 사전의 정의에 따르면, "Aspect"은 "사물의 면, 국면, 관점"으로 정의되어 있다. 소프트웨어 시스템은 여러가지 관점에서 바라볼 수 있다, 또는 여러 가지 단면을 가지고 있고 있다. 예를 들어, 자금 이체를 하는 프로그램을 작성한다고 생각해 보자. 출금계좌와 입금계좌, 그리고 이체금액을 입력받아 SQL 문장 또는 함수 한 번 돌리는 것으로 끝나는가? 절대 아니다. 먼저, 해킹을 방지하기 위해 사용자가 적절한 보안 프로그램을 설치했는지 점검하는 코드도 있어야 하고, 사용자가 인증되었는지 점검하는 코드도 써야 하고, 상대방 은행에서 적절하게 처리되었는지도 점점해야 하고, 혹시 사용자가 이체버튼을 두 번 누른 것은 아닌가 체크해야 하고, 시스템 로그도 남겨야 한다. 즉, 구현하려고 하는 기능 뿐 아니라 보안, 인증, 로그, 성능와 같은 다른 기능들도 녹아 있어야 한다. 어쩌면 이체를 위한 코드보다 잡다한 다른 측면의 문제들을 다루는 코드가 더 길어질 수 있다. 이런 코드들은 입금이나 출금 같은 다른 곳에서 들어가야 한다. 구현하려고 하는 비즈니스 기능들을 Primary(Core) Concern, 보안, 로그, 인증과 같이 시스템 전반적으로 산재된 기능들을 Cross-cutting concern이라고 부른다. AOP는 Cross-cutting concern를 어떻게 다룰 것인가에 대한 새로운 패러다임이라고 할 수 있다.<br />
 <br />
 AOP는 구조적 방법론에서 객체지향 방법론으로 전환처럼 시스템 개발에 관한 전체적인 변화는 아니다. Object-Oriented Programming이 Aspect-Oriented Programming으로 대체되는 일은 없을 것이다. AOP는 구조적 방법론에도 적용될 수 있고, 다른 방법론에도 다 적용될 수 있지만, 주로 객체지향방법론이 가지는 단점을 보완하는 것으로 묘사되고 있다. 그러면 객체지향 프로그래밍이 또는 다른 이전의 프로그래밍 기법들이 Cross-cutting Concern를 어떻게 다루는지 알아보자. 매우 간단하다. Primary Concern를 구현한 프로그램에 함께 포함시켰다. 그것이 단 한 줄의 메소드 호출이라 하더라도. 많은 프로그래머들은 거의 모든 프로그램에 산재된 로그하는 단 한 줄의 코드를 찾아서 바꾸어 본 경험이 있을 것이다. 또는 간단하게 생각하고 프로그램을 수정하려고 했는데, 도데체 어디를 수정해야 되는지 모르게 코드가 길고, 알 수 없는 코드들이 자리를 차지하고 있을 때의 난감함. Primary concern, Cross-cutting concern이 하나의 프로그램 안에 들어가게 되면, 프로그램을 이해하기가 힘들고, Cross-cutting concern 코드가 여기저기에 산재되어 수정하기 힘들게 된다. 당연히 생산성 떨어지고, 품질 떨어지고, 유지보수 비용 많이 들게 된다.<br />
 <br />
 그럼 AOP는 Cross-cutting concern를 어떻게 처리하는가? 이것도 매우 간단하다. 새로운 아이디어라고 할 수도 없다. Primary Concern 구현하는 코드 따로, Cross-cutting concern 구현하는 코드 따로 쓰고, 나중에 두 개 조합하게 완벽한 어플리케이션 만들겠다는 것이다. 기술 용어로 쓰면, Advice(Cross-cutting concern 구현한 코드)와 Primary concern 구현한 코드를 Point-cut 정보를 이용해서 Weaving(조합)하는 것이 AOP가 이 문제를 다루는 방법이다.<br />
 <br />
 <img src="http://image.hanbitbook.co.kr/blog/7609/1090201606@ado_fig1.jpg" alt="그림1" height="299" width="552" /><br />
 <br />
 기술적 용어로서의 "Aspect"은 "Advice"와 "Point-cut"을 함께 지칭하는 단어이다. Point-cut은 어떤 Advice를 Code 어느 위치에 둘 것인가 하는 것이다. 예를 들면, 로그 기능을 구현한 Advice는 Code 속에 있는 모든 public 메소드가 수행되고 나면, 그 마지막에 실행되어라 라고 지정한 것이라 할 수 있다.<br />
 <br />
 이전까지의 객체지향 프로그래밍은 Cross-cutting concern을 정적으로 어플리케이션에 결합시킨 반면 AOP는 동적으로 Cross-cutting concern를 다룬다고 표현하기도 합니다. 용어에서도 알 수 있듯이 AOP는 소프트웨어 엔지니어링 원칙 중에 하나인 "Separation of concern"를 구현하려고 하고 있습니다. 이러한 문제들을 다루고 있는 분야 중에 하나는 디자인 패턴할 수 있고, 예를 들어, Visitor 패턴은 정적인 구조를 동적으로 바꾸려고 합니다. AOP가 현재까지 나온 방법들 중에서 Cross-cutting concern를 다루는 가장 좋은 방법인가 하는 질문엔 아직 답하긴 힘들 것 같습니다. 그럼에도 분명 언제가는 책상 위에 관련 서적 한 권 있어야 할 것 같은 분야가 될 것 같습니다.<br />
<br />
<br />
 http://network.hanbitbook.co.kr/tb_response.php?bi_id=968<br />
			 ]]> 
		</description>
		<category>Task</category>

		<comments>http://namkee.egloos.com/3081769#comments</comments>
		<pubDate>Thu, 08 Feb 2007 01:18:55 GMT</pubDate>
		<dc:creator>namkee</dc:creator>
	</item>
	<item>
		<title><![CDATA[ 녹킹 온 헤븐스 도어(Knock'in On Heaven's Door) ]]> </title>
		<link>http://namkee.egloos.com/2974106</link>
		<guid>http://namkee.egloos.com/2974106</guid>
		<description>
			<![CDATA[ 
  <div align="center"><img class="image_left" border="0" onmouseover="this.style.cursor='pointer'" alt="" src="http://pds4.egloos.com/pds/200701/13/95/c0043595_0201549.gif" width="187" height="281" onclick="Control.Modal.openDialog(this, event, 'http://pds4.egloos.com/pds/200701/13/95/c0043595_0201549.gif');" align="left" /><br />
</div><p align="center">Knock'in On Heaven's Door / 1997 / 독일<br />
</p><p align="center">&nbsp;관람 : 고등학교시절 비디오로 1차 관람으로 밥딜런을 알게됨, 대학 1학년 시절 영상파일로 2차 관람 감동으로 눈물 한바가지, 비디오가게로 직행. 비디오로 다시봄. 그리고 3시간전 포스팅을 위해 줄거리만보려다 끝까지 다봐버렸다.<br />
</p><p align="center">&nbsp;강한 주인공과 약한 주인공이 만나서 이끌어나가는 이야기들은 대부분 이야기가 흘러감에 따라 강한 주인공의 약한 부분을 보여주고 약한 주인공의 강한 모습을 보여주며 재미를 만들어간다. 뭐 우연한 약한 주인공의 살인과 너무나 자연스러움.. 강한 주인공이 가지고 있는 의외성의 컴플렉스라던가 약점.. 그런것들이 재미의 포인트 혹은 큰 가지로 전체 이야기를 만들어가는 영화들이 꽤 많았던 것으로 기억한다.<br />
&nbsp;그런것 처럼 이영화에서는 그런&nbsp;지점들이 감동을 만들어 낸다. 주인공들의 그러한 첫인상들이 깨어질때 카타르시스가 느껴진다.(루디가 마틴의 약을 위해서 총을 쏘는 장면, 마틴이 엄마 품에서 흐느끼는 장면) 영화 전반적으로 코미디 요소를 너무 많이 품고 있어서 감동에 집중이 안되는 단점이 있지만 또 전반적인 웃기는 주변 요소들이 감동의 깊이를 더해준다랄까?(나에겐 너무 사치표현인가..;)<br />
<br />
&nbsp;코미디... 희극은 과연 극중 주인공이 행복한게 우선인가 극을 보는 이가 행복한게 우선인가. 분명 둘다를 만족하는게 희극이라고 하기엔 우리가 알고 있는 희극이라 불리는 이야기들중에 범주에서 벗어난게 많다.. 뭐 결론은 모르겠네.. 아직 주관적으로 이야기를 구분짓고 이름짓는 지경에까지는 다다르지 않았으니 어쨌든 행복하게 본영화이니 그리고 줄거리야 출발 비디오 여행에서 줄기차게 설명해 주었으니 패스!<br />
<br />
<br />
<br />
<strong>내가 짚은 인상적인 순간들..</strong><br />
<br />
<strong>#1</strong></p><div style="text-align:center"><img class="image_mid" border="0" onmouseover="this.style.cursor='pointer'" alt="" src="http://pds4.egloos.com/pds/200701/13/95/c0043595_01013572.jpg" width="400" height="240" onclick="Control.Modal.openDialog(this, event, 'http://pds4.egloos.com/pds/200701/13/95/c0043595_01013572.jpg');" /></div> <div align="center">마틴 : 여기쯤 있나요..?</div><div align="left">&nbsp;</div><div align="left">&nbsp;</div><div align="right">&nbsp;</div><div align="left">시작 부분에 병원에서 주인공 마틴이 의사와 대화중에서 머릿속에 자라고있는 암덩이가 어디쯤있는지 물어보는장면...</div><div align="left">분명 아직 자신이 살날이 얼마 남지 않았음을 모르는 상황인데도 눈빛에 슬픔이 묻어난다...</div><div align="left">&nbsp;</div><div align="left"><span style="COLOR: #cc66cc">&nbsp;난 이런 남자 배우가 좋더라.. 분명 잘생긴것 말고도 사람 눈을 기억하게 만드는 뭔가가 있어!</span></div><div align="left"><span style="COLOR: #cc66cc">포스팅 하면서 찾아봤는데 실버스타 할아버지 나왔던 드리븐 이란 레이싱&nbsp;영화에서 본기억이 나고..</span></div><div align="left"><span style="COLOR: #cc66cc">깅 아더 였나에도 나왔단다.. 내기억이 맞긴 맞았다..</span></div><br />
<br />
<br />
<br />
<br />
<br />
<br />
<div align="left"><strong>#2</strong></div><div align="center"><div style="text-align:center"><img class="image_mid" border="0" onmouseover="this.style.cursor='pointer'" alt="" src="http://pds5.egloos.com/pds/200701/13/95/c0043595_01015231.jpg" width="400" height="240" onclick="Control.Modal.openDialog(this, event, 'http://pds5.egloos.com/pds/200701/13/95/c0043595_01015231.jpg');" /></div>루디 :&nbsp;죽는다는게 어차피 고통스러운거 아닌가요?<br />
</div><div align="right">루디가 골수암 말기 선고를 받는다...</div><div align="right">&nbsp;</div><div align="right"><span style="COLOR: #cc66cc">사실 기억에 남는 장면은&nbsp;아니었지만 마틴과 짝을 맞추고 싶었다...</span></div><div align="right">&nbsp;</div><div align="right">&nbsp;</div><div align="left">&nbsp;</div><div align="left">&nbsp;</div><div align="left">&nbsp;</div><div align="left">&nbsp;</div><div align="left">&nbsp;</div><div align="left">&nbsp;</div><div align="left">&nbsp;</div><div align="left">#3<div style="text-align:center"><img class="image_mid" border="0" onmouseover="this.style.cursor='pointer'" alt="" src="http://pds5.egloos.com/pds/200701/13/95/c0043595_01015620.jpg" width="400" height="240" onclick="Control.Modal.openDialog(this, event, 'http://pds5.egloos.com/pds/200701/13/95/c0043595_01015620.jpg');" /></div></div><div align="center">루디 : 간호사, 데킬라 파티를 할건데 소금과 레몬이 어딨죠?</div><div align="left">&nbsp;</div><div align="left">&nbsp;</div><div align="left">&nbsp;</div><div align="left">영화 내내 대칭을 이루는 원근 구도가 많이 나온다. 먼곳은 대부분 밝다. </div><div align="left">저 밝은곳이 door 인가..? </div><div align="left">두 주인공은 늘 그 곳을 향해 걸어가는 모습을 보여준다. </div><div align="left">&nbsp;</div><div align="left">병원이건만 환자복 아닌 잠옷을 입고 데킬라 마시러 가는 마틴과 루디...</div><div align="left">&nbsp;</div><div align="left"><span style="COLOR: #cc66cc">둘이 같이 걸어가고 마틴은 담배, 루디는 데킬라 병을 드는건 마지막 장면에서도 같다. 마지막 장면의 예고편?</span></div><div align="left">&nbsp;</div><div align="left">&nbsp;</div><div align="left">&nbsp;</div><div align="left">&nbsp;</div><div align="left">&nbsp;</div><div align="left">&nbsp;</div><div align="left">&nbsp;</div><div align="left">&nbsp;</div><div align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #4</div><div style="text-align:center"><img class="image_mid" border="0" onmouseover="this.style.cursor='pointer'" alt="" src="http://pds4.egloos.com/pds/200701/13/95/c0043595_01014527.jpg" width="400" height="240" onclick="Control.Modal.openDialog(this, event, 'http://pds4.egloos.com/pds/200701/13/95/c0043595_01014527.jpg');" /></div><br />
<div align="center">행크 : 잘했다 압둘!</div><div align="center">,</div><div align="center">&nbsp;</div><div align="center">압둘 : 내 차에 앉았잖아</div><br />
<br />
<div align="right"><span style="COLOR: #cc66cc">시종일관 다른 배역들에 비하면 실수라고하기에도 미안한 에피소드를 저지르는 두 주인공!</span></div><div align="right"><span style="COLOR: #cc66cc">이들도 주인공이지 암...</span></div><div align="right"><span style="COLOR: #cc66cc">그리고 또하나의 주인공 벤츠 230 연청색 SL.. 이쁜 스포츠카...</span></div><div align="right"><span style="COLOR: #cc66cc">그리고 차에 앉아버린 영화속에선 지극히 평범한(!) 소년...</span></div><div align="right"><span style="COLOR: #cc66cc"></span>&nbsp;</div><div align="right"><span style="COLOR: #cc66cc"></span>&nbsp;</div><div align="right"><span style="COLOR: #cc66cc"></span>&nbsp;</div><div align="right"><span style="COLOR: #cc66cc"></span>&nbsp;</div><div align="right"><span style="COLOR: #cc66cc"></span>&nbsp;</div><div align="right"><span style="COLOR: #cc66cc"></span>&nbsp;</div><div align="right"><span style="COLOR: #cc66cc"></span>&nbsp;</div><div align="right"><br />
<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #5 </div><div style="text-align:center"><img class="image_mid" border="0" onmouseover="this.style.cursor='pointer'" alt="" src="http://pds5.egloos.com/pds/200701/13/95/c0043595_01011459.jpg" width="400" height="240" onclick="Control.Modal.openDialog(this, event, 'http://pds5.egloos.com/pds/200701/13/95/c0043595_01011459.jpg');" /></div><br />
<br />
<div align="center">우연히 마주친 꼬마에게 피우던 시가를 건내주는 마틴.</div><br />
<br />
<div align="right"><span style="COLOR: #cc66cc">왠지 의도된 희극적 요소 같은데 사실 별로 웃음주진 못했다.</span></div><div align="right"><span style="COLOR: #cc66cc">왠지 오마주나 패러디 느낌도 나고..</span></div><div align="right"><span style="COLOR: #cc66cc">아무튼 꼬마가 너무 귀엽고 이 장면도 너무 귀엽다.</span></div><p><br />
<br />
<br />
&nbsp;</p><p>&nbsp;</p><p>#6<br />
</p><div style="text-align:center"><img class="image_mid" border="0" onmouseover="this.style.cursor='pointer'" alt="" src="http://pds5.egloos.com/pds/200701/13/95/c0043595_0101417.jpg" width="400" height="240" onclick="Control.Modal.openDialog(this, event, 'http://pds5.egloos.com/pds/200701/13/95/c0043595_0101417.jpg');" /></div> <p align="center">사물은 보이는 것보다 가까이에 있음.<br />
<br />
<br />
루디 : 내겐 바다면 충분해...</p><p align="left"><br />
어디로 갈지 고민하는 마틴과 루디... 그곳이 멀지 않음을 얼마 남지 않았음을...<br />
조금은 어두운 복선과 함께 루디는 그저 바다면 된다고 이야기 한다..<br />
<br />
<span style="COLOR: #cc66cc">차에 타면서 늘 저 문구 보면서 늘 다른 생각들을 해왔는데 '죽음'이라는 단어와 연관 시키니 제법</span><br />
<span style="COLOR: #cc66cc">충격적인 복선이 탄생했다. 감독 센스 하고는..</span><br />
<br />
</p><p align="left">&nbsp;</p><p align="left"><br />
<br />
<br />
<br />
<br />
#7 <div style="text-align:center"><img class="image_mid" border="0" onmouseover="this.style.cursor='pointer'" alt="" src="http://pds4.egloos.com/pds/200701/13/95/c0043595_02014255.jpg" width="400" height="240" onclick="Control.Modal.openDialog(this, event, 'http://pds4.egloos.com/pds/200701/13/95/c0043595_02014255.jpg');" /></div></p><p align="center">마틴과 루디가 경찰에 전달한 일급 문서.<br />
<br />
<br />
<span style="COLOR: #cc66cc">이런게 코미디지 ㅋㅋㅋ</span><br />
<br />
<br />
<br />
<br />
<br />
<br />
</p><div align="right">#8</div><div style="text-align:center"><img class="image_mid" border="0" onmouseover="this.style.cursor='pointer'" alt="" src="http://pds4.egloos.com/pds/200701/13/95/c0043595_02015842.jpg" width="400" height="240" onclick="Control.Modal.openDialog(this, event, 'http://pds4.egloos.com/pds/200701/13/95/c0043595_02015842.jpg');" /></div> <p align="center">약사 : 이건 강도가 높은 혈액 순환 촉진제 입니다. 의사의 처방전이 있어야만 해요.<br />
<br />
(장전, shoot)<br />
</p><div align="right">발작을 일으켜 쓰러진 마틴을 위해 약을 사러간 루디...</div><div align="right">나약한 루디 강해지다...</div><div align="right">&nbsp;</div><div align="right"><span style="COLOR: #cc66cc">대부분의 사람들도 그랬을거고 영화 감독의 의도도 그러했을거고..</span></div><div align="right"><span style="COLOR: #cc66cc">이분에서 뒷골에서 띵해오는 카타르시스를 느낀다..</span></div><div align="right"><span style="COLOR: #cc66cc">긴장감 고조시키는 음악과 슬로우모션도 그렇고..</span></div><div align="right"><span style="COLOR: #cc66cc">너무 진부한 카타르시스지만... 이런거 좋드라.. 감동적이야..</span></div><div align="right">&nbsp;</div><div align="right">&nbsp;</div><div align="right">&nbsp;</div><div align="right">&nbsp;</div><div align="right">&nbsp;</div><div align="right">&nbsp;</div><div align="right">&nbsp;</div><div align="left">&nbsp;</div><div align="left">&nbsp;</div><div align="left">#9</div><div align="right"><div style="text-align:center"><img class="image_mid" border="0" onmouseover="this.style.cursor='pointer'" alt="" src="http://pds5.egloos.com/pds/200701/13/95/c0043595_02015610.jpg" width="400" height="240" onclick="Control.Modal.openDialog(this, event, 'http://pds5.egloos.com/pds/200701/13/95/c0043595_02015610.jpg');" /></div></div><p align="center">위기봉착 마틴과 루디.<br />
</p><p align="left"><span style="COLOR: #cc66cc">딱 보면 떠오르겠지만 그렇다! '주유소 습격사건!'</span><br />
<span style="COLOR: #cc66cc">결과야 뭐..</span><br />
<span style="COLOR: #cc66cc">상황이 가져다주는 웃음까지 선사해주신다. 아이고 감사</span><br />
<br />
</p><p align="left">&nbsp;</p><p align="left">&nbsp;</p><p align="left"><br />
<br />
<br />
#10<br />
</p><div style="text-align:center"><img class="image_mid" border="0" onmouseover="this.style.cursor='pointer'" alt="" src="http://pds4.egloos.com/pds/200701/13/95/c0043595_02013975.jpg" width="400" height="240" onclick="Control.Modal.openDialog(this, event, 'http://pds4.egloos.com/pds/200701/13/95/c0043595_02013975.jpg');" /></div> <p align="center">루디 : 내인생 최고의 섹스였어.<br />
<br />
<br />
행크 : 그리고 마지막이었지.<br />
<br />
</p><p align="left"><span style="COLOR: #cc66cc">너무 유명한 장면인가? 나는 왜이렇게 익숙한 장면이지?</span><br />
<br />
</p><p align="left">&nbsp;</p><p align="left"><br />
&nbsp;</p><p align="left"><br />
<br />
<br />
<br />
#11</p><div style="text-align:center"><img class="image_mid" border="0" onmouseover="this.style.cursor='pointer'" alt="" src="http://pds5.egloos.com/pds/200701/13/95/c0043595_02013157.jpg" width="400" height="240" onclick="Control.Modal.openDialog(this, event, 'http://pds5.egloos.com/pds/200701/13/95/c0043595_02013157.jpg');" /></div><br />
<br />
<div align="center">보스 : 바다를 본적이 없다...</div><div align="center">&nbsp;</div><div align="center">그럼 뛰어야 겠군.. 시간이 얼마 안남았거든..</div><div align="center">.</div><div align="center">.</div><div align="center">.</div><div align="center">&nbsp;</div><div align="center">천국에선 늘 한가지 이야기만 하지..</div><div align="center">... 바다 ..</div><div align="center">&nbsp;</div><div align="center">노을이 질때.. 그때 불덩이가 바다로 녹아드는 모습은 </div><div align="center">졸라 멋있지..</div><div align="center">&nbsp;</div><div align="center">그후에 남은 빛이라고는 마음속에 빛나는 촛불같은 빛이지..</div><div align="center">&nbsp;</div><div align="center">.</div><div align="center">.</div><div align="center">.</div><div align="center">&nbsp;</div><div align="center">마틴 : 루디... 할말이 있어</div><div align="center">&nbsp;</div><div align="center">루디 : 알아... 내가먼저 말하지..</div><div align="center">&nbsp;</div><div align="center">두려워 할 것 없어..</div><br />
<br />
<div align="center"><embed src="mms://mms.oolim.net/jazzpiano/BillEvans/영상/door.wmv" width="320" height="240" autostart="0"></div><div align="center">&nbsp;</div></embed><br />
마지막 장면의 감동은 친구 블로그에서 불펌하도록 하겠다.(불펌 안하려 했으나 그대로 포스팅 해오기엔 내가 적고 싶은 글이 많고 링크시키자니 포스팅에 의의가 없는것 같아서 불펌했다.)<br />
퍼온 블로그 =&gt; <a href="http://vndfbfkd.tistory.com/">http://vndfbfkd.tistory.com</a><br />
<br />
<br />
<br />
&nbsp;			 ]]> 
		</description>
		<category>움직이는그림</category>

		<comments>http://namkee.egloos.com/2974106#comments</comments>
		<pubDate>Fri, 12 Jan 2007 17:50:13 GMT</pubDate>
		<dc:creator>namkee</dc:creator>
	</item>
	<item>
		<title><![CDATA[ 깊이에의 강요 / 파트리크 쥐스킨트 | 김인순옮김 ]]> </title>
		<link>http://namkee.egloos.com/2970267</link>
		<guid>http://namkee.egloos.com/2970267</guid>
		<description>
			<![CDATA[ 
  <p align="right"><div style="text-align:center"><img class="image_mid" border="0" onmouseover="this.style.cursor='pointer'" alt="" src="http://pds3.egloos.com/pds/200701/11/95/c0043595_11013528.jpg" width="214" height="285" onclick="Control.Modal.openDialog(this, event, 'http://pds3.egloos.com/pds/200701/11/95/c0043595_11013528.jpg');" /></div></p><ul><li><div align="left">획득 : 책을 사면&nbsp;언제나 산 날짜와 이름 가게이름정도는 늘 적어놓는데 찾아보니 없네.. 아마도 파트리크 책들 다 사고 모을때쯤이니까 대략 11월정도 될듯하다.&nbsp;</div></li><li><div align="left">읽음 : 대략 2틀 정도.. 지하철, 마을버스 수업시간 이용해서 다 읽었다.</div></li><li><div align="left">위치 : 앞 책장 맨 위층 아래 층.. 중간</div></li></ul><p align="left"><strong>어떻게 샀었지?...</strong></p><p align="left">&nbsp; 그래 2달 전쯤이었을 거다. 2006년 11월.. 3학년 2학기 프로젝트 숙제의 연속. 프로젝트 발표는 교수한테 여지없이 깨지고 공부는 전혀 진전이 없었고 프로젝트 팀원 들도 서로 힘들고 도망치고 싶었던 그때 였다. 그 깝깝함과 도망치고싶은 욕구가 온몸에 아드레날린보다 널리 퍼져있을때&nbsp;전산센터 알바를 끝내고 또 이어폰꽃고 볼륨은 최대로 음악은 최대한 정신없는것으로 해놓고 그렇게 거닌다. 담배 연기가 몸속에 들어가 그나마 서로 붙어 심장을 rpm을 올려주던 아드레날린과 도피욕을 화해시키는 것도 잠시... 걸음이 다달은 곳은 서점이었고 책장 앞에 섰다.&nbsp;자주가지만 갈때마다 낯선 청맥... 신기하게도 내가 갈때면 중고등학교 참고서 코너나 어린이 서적 근처에 사람이 많다..&nbsp; 버릇처럼 사회과학 코너에서 머뭇거리다 그 두께와 한번 펼쳐 보았을때 찾아드는 낯선 단어들의 공격에 설레설레 칠즘에 수필코너가 눈에 들어왔고 사회과학 서적에 비하면 정말 겸손한 글자크기와 왠만하면 양장본으로 이쁘게 포장되어있어 반갑기 그지없더라. </p><p align="left">&nbsp;좀머씨 이야기.. 그래 고등학교때 유지태 때문에 읽었던거 같아... 유지태가 파트리크 수필 좋아한다고 했었어.. 근데 그때 유지태가 좋아하는 좀머씨 이야기를 왜 읽었는지는 기억이 나질 않는다. 뭔가 사연이 있었던듯 한데.. 아무튼 좀허무하고 밍숭맹숭한. 내용 이었어.. 그래 좀머씨 이야기.. 향수! 맞어 대학 1학년때 읽었어... 근대 역시나 어떻게 읽게 되었는지는 기억이 안나는군.. (뭐 중요한 건 아니니..) 그렇게 두권의 이미 읽었던 책들의 기억들이 너무나도 반가워서 금새 기분이 좋아져 버렸다. 그리고 연속으로 서있던 파트리크 책들이 눈에 들어왔다. 비둘기, 사랑을 생각하다. 깊이에의 강요.... 또 있었는데.. 아무튼 양장본임에도 생각보다 저렴한 가격과 일단 책을 지르면 후회가 별로 안된다는 위안으로 3권을 사고 말았다. 각권 7천 5백원 도합...2만 2천 500원... 음..</p><p align="left">&nbsp;</p><p align="left"><strong>&nbsp;세가지 이야기... / 첫번째 이야기...</strong></p><p align="left">&nbsp;세상에는 참 기준이 모호한 판단들이 많다. 중학교 1학년 수학시간 집합배울때도 배우듯이 전혀 논리적일수 없는 판단이며 주장임에도 불구하고 사람들 사이에선 중요하게 의식되고 인지된다. 너 이쁘다. 잘생겼다. 잘한다. 훌륭하다. 적당히. 사랑해...(이건 아닌가..-_-;) 이건 왜 그런지 정확하게 정의되지 못했지만 기분이 좋은 말들이다. 대부분의 사람들이 왼쪽을 향한 시선으로 주로 이런 말들을 한다.(거짓말이란 이야기..)</p><p align="left">&nbsp;반면에 못생겼다. 엉망이다. 내게 이익이 되는 숫자만큼,.. 뭐 어느정도인지 가늠하기 힘들지만 들으면 가히 기분 다운되는 말들이다. 대부분의 사람들이 뒤에 숨어서 주로 이런 말들은 한다..</p><p align="left">&nbsp;세상에 진행되는 요절한 천재들에 관한 담론들을 생각해보게 한게 첫번째 수필 '깊이에의 강요'. 요새 왠만한 반전 스토리의 이야기에 면역된 사람이라면 읽다가 결론을 다 알아버릴 만한 약한 반전의 약간은 허무하고 짧은 이야기지만 블랙 코미디물 보고나서 지어지는 씁쓸한 웃음처럼 뭔가 뒷맛이 개운치 않다. 그렇게 갈구하던 깊이'있는' 이라는 판단과 그 경지는 단지 기자의 혀끝의 말 한마디 였을 뿐인데..</p><p align="left">&nbsp;내가 쫒고 있는.. 갈구하고 있는것도 결국 깊이다. 아무도 그것의 판단 기준을 모르고 어느것이 깊고 어느것이 얇으며 있고 없고를 알수없는 그 알량한 세치 혀에서 나오는 단어하나처럼 결국엔 아무것도 아닐 밖으로 보이는 남에게 인정받는 그것을 위해서 살고 있잖은가.. 응? </p><p align="left">&nbsp;근데... 그거 버리기 힘든거.. 알지...? 작가도 결국엔 죽었잖냐... </p><p align="left">&nbsp;</p><p align="left"><strong>&nbsp;세가지 이야기... / 두번째 이야기...</strong></p><p align="left">&nbsp;난 뭐 도박을 잘 못하니까 즐겨하지않지만 확률과 수학적인 순간의 판단을 가지고 승부를 펼치는 도박도 재미있고.. 상대방을 속이는 절묘한 치팅으로 나는 승부의 도박도 재밌지만 적절한 재미를 주는건 바로 뻥카(!).. 망통으로 광땡도 잡는 도박의 세계 아닌가...-_-;;</p><p align="left">&nbsp;어릴때 화투, 쌈치기, 돈치기, 카드 뭐 그쪽(!) 분야로는 다 잘하는 친구가 있었는데 그친구가 놀라운 점은 패가 평균적으로 다른 사람들에 비해 잘나오는게 아닌데도 많이 딴다는 거다. 가만히 살펴보니 적절한 뻥카는 도박판(!)에 활력소로 긴장도 풀어주고 다음 뻥카를 위한 사전 전략이 된다. 나같이 거짓말 못하는 사람이 뻥카 치면 금방 들통 나지만. 그녀석은 정말 모르겠드라. 암튼..</p><p align="left">&nbsp;책 내용은 도박에 치팅이나 뻥카와 관련이 없다. 그냥 책 읽다가 생각이났다. </p><p align="left">&nbsp;파트리크가 정말&nbsp;글을 섬세하고 독자를 몰입시키는 능력이 있음은 바로 이 수필에서 느꼈다. 나도 왠지 속은 느낌이다. 후반부 결말에 이르기까지 나도 속았다. 그냥 글 쓰여져 있는대로 믿고 그대로 읽으며 상황을 전개시킨다. 마치 자신도 모른체 상황상황을 녹음한듯한 느낌이 들정도 였으니까.</p><p align="left">&nbsp;책 내용 이야기는 그렇고 아무튼 끝은 예상치 못하게 허무하다... 읽었던 나까지 당황스럽다. 난 죄지은게 없는데 왠지 난 안그랬던 것처럼 의식하게 된다. </p><p align="left">&nbsp;이건 좀 비약일지 모르겠으나 혹시.. 밖으로는 표출안하는 열등감을 가진 보통의 평범한 못난 사람들... 줏대없이 힘에 기대려고 이힘과 저힘 사이를 저울질하는 비겁한 평범한 사람들... 그런 보통의 사람들의 헛된 망상과 가식을 꼬집고 싶은게 아니었을까 하는 생각이 드네.. 역시나 비약이낙.</p><p align="left"><strong></strong>&nbsp;</p><p align="left"><strong>&nbsp;세가지 이야기... / 세번째 이야기...</strong></p><p align="left">&nbsp;장인 뮈시르의 유언. 솔직하게 쓰자면 재미없다. 왠지 하나의 사건이나 에피소드를 비꼬는 형식의 글같은데 뭐가 모티브인지 동시간, 공간을 살지 않은 나로서는 도무지 이해와 재미가 전혀 따라 오지 않는다. 왠지 허무한 블랙 코미디 같다는 생각도 들고. 마지막까지 뒤통수 때리는 반전을 기대했으나 여전히 자욱하다. 여기저기 해설하고 뭐 찾아봤는데 납득이 가지 않던걸.. 과연 그 해설은 뭘 느끼고 쓴건지 원... 거짓말쟁이들..</p><p align="left">&nbsp;</p><p align="left"><strong>작가의 이야기 / 문학적 건망증..</strong><strong></strong></p><p align="left">&nbsp;사람이 너무 완벽할순 없다라는 생각이(바램이) 가끔 방송에서 보도되는 몇몇 천재들과 모든걸 가진 사람들의 모습을 통해서 안타깝게 깨어지고 말았던 경우가... 나만 있는건 아니겠지? 파트리크 쥐스킨트도 뭐 사람이니 자신의 건망증 이야기를 꺼낸것에서 나는 또 자위거리 찾은듯이 인간미까지 매료되어가고 있었다. 자신의 증상으로 꼬집은.. 읽은 책들의 제목은 기억하고 있는가? 글쓴이는? 내용은 기억하고 있나? 당신이 기억하고 있는 책의 부분이 전체 책에서 어느정도 양이라고 생각하지? 이소설과 저소설 주인공이 헷갈리진 않는가?.. 등등의 독서량이 절대 부족한 나이지만 그나마 나쁜머리라서... 그래도 대부분의 사람들이 그럴거라며 자위하고 있었는데 이런.. 파트리크도 이렇다니.. 하며 내심 좋아했다. 그래.. 왠지 같은 레벨 같잖니..(마치 '승부'라는 책속의 수필속에서 주위 평범하게 비겁한 구경꾼들 처럼 말이지..)</p><p align="left">&nbsp;근데 마지막에 또 뒤통수를 치더군.. 허허.. 왠지 사람이라면 다그러니 자신도 고민이라고 할줄 알았는데.. 심각한 문학적 건망증을 앍고있으니 큰일이라는.. 뭐 어차피 당연한 이야기를 하네... 당연한데도 왠지 속은 기분.. </p><p align="left">&nbsp;아무튼 그런 상황인 파트리크도 건망증속에서도 기억하려고 안간힘 쓰는 그... 문구..&nbsp; 시구..&nbsp; 그것만 기억하자... 너... 나.? 너를 .? .............(나도 갑자기 기억이 나지 않아 다시 찾아봤다... 진짜다..-_-;; )</p><p align="left">&nbsp;너는 네를 변화시켜야 한다.(헉 뭔가 이상하다 했더니 난 또 까먹었다..-_-)</p><p align="left">&nbsp;너는 네 삶을 변화시켜야 한다.</p><p align="left">&nbsp;음.. 나는 이문구를 기억하려고나 했을까?..</p>			 ]]> 
		</description>
		<category>책</category>

		<comments>http://namkee.egloos.com/2970267#comments</comments>
		<pubDate>Thu, 11 Jan 2007 15:19:56 GMT</pubDate>
		<dc:creator>namkee</dc:creator>
	</item>
</channel>
</rss>
