달력

72025  이전 다음

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

아주 큰~~~ 삽질

.NET/C# 2006. 7. 25. 19:46

현재 ASP.NET 2.0 으로 개발하고 있는데, 데이터베이스 관련해서 프레임워크를


하나 만들어서 사용한다.


COM+ 사용 안하고 멀티 트랜잭션 가능하고, 테이블과 객체 매핑 되고, Stored Procedure 에


최적화 시켜놨당.


그런데, 웹페이지 띠우고 새로고침 몇십번 하면 tcp resource 부족으로 먹통이 된다. ㅎㅎ


왜 그러나~ 하고 코드 자세히 뜯어보니...


private ArrayList dbts = new ArrayList();



public void CreateTransaction(bool isTransaction)
{


  DBTransaction dbt = new DBTransaction(true);

  dbts.add(dbt);

}


public void ReleaseTransaction()

{

    foreach(DBTransaction dbt in dbts){

        dbts.Clone();

    }

}


대충 이런 코드가 있는데... 빨간색 부분.... 허걱..


Close() 해야 하는데, Clone() 이당...


Visual Studio 에 코드 자동완성 뜨는거에 대충 엔터쳐서 작성해 놨더니


저렇게 되었음.



즉 트랜잭션 열어놓구, 종료두 안하고 ArrayList 를 계속 복사한 상황이다.


빨리 알아냈으니 다행이지 큰일날뻔했네 ㅎ



Posted by tornado
|

괜찮은 Chart 하나~

.NET/C# 2006. 7. 20. 17:12
Posted by tornado
|

마이크로소프트의 고객지원 페이지에 있는 해당 현상과 관련된 글입니다

 

수용할 수 있는 최대 개수의 연결이 이미 있으므로 지금 이 원격 시스템에 더 이상 연결을 작성할 수 없습니다.

 

-원인-

컴퓨터가 호스트할 수 있는 최대 개수의 인바운드 연결에 도달한 경우 이러한 문제가 발생합니다.

Windows XP Professional의 경우에는 네트워크를 통해 최대 10대까지 다른 컴퓨터에 동시에 연결할 수 있습니다. 이 제한에는 모든 전송 및 리소스 공유 프로토콜이 포함됩니다. Windows XP Home Edition의 경우에는 네트워크를 통해 최대 5대까지 다른 컴퓨터에 동시에 연결할 수 있습니다.


XP PRO버전의 경우 10대까지가 동시접속 제한숫자이군요.

이 제한을 풀수는 없다고 나왔구요


대신 이 문제를 다소나마 다른 방법으로 문제를 해결할 수 있도록 제시하고 있군요


원문은 이렇습니다

활동이 없는 모든 파일, 인쇄, 명명된 파이프(Named Pipe) 또는 메일 슬롯 세션은 AutoDisconnect 시간이 만료되면 자동으로 연결이 끊어집니다. AutoDisconnect 시간의 기본값은 15분입니다. 세션의 연결이 끊기면 10개의 연결 중 하나가 사용 가능한 상태가 되어 다른 사용자가 Windows XP 시스템에 연결할 수 있습니다. 따라서 AutoDisconnect 시간을 줄이면 서버 목적을 위해 많이 사용되지 않는 시스템에서 10개나 5개로 제한된 연결로 인해 사용자가 겪게 되는 문제를 줄이는 데 도움이 될 수 있습니다.

명령 프롬프트에서 다음 명령을 실행하여 AutoDisconnect 시간을 구성할 수 있습니다.

net config server /autodisconnect:time_before_autodisconnect

시간은 분 단위로 지정합니다.


그러니까 지금 10대의 컴퓨터가 서버에 연결되어 있다고 가정해보죠

연결된 10대의 컴퓨터가 쉬지 않고 계속해서 작업을 하고 있다면 10대의 연결은

계속적으로 유지됩니다


다른 컴퓨터들은  최대연결초과로 인해 서버에 접속할 수 없죠

그런데 위에 제시한 자동연결끊김 기능의 시간을 잘 활용하면 어느 정도 서버로의

유연한 연결이 가능해질 수  있게 되네여 .

기본시간이 15분이죠.  한 컴퓨터가 15분이상의 아무런 작업신호를 보내지 않으면

그컴퓨터는 자동으로 연결해제 되는 거죠


자 이 시간이 길면 길수록  어느 한 컴퓨터의 연결이 끊기는데 걸리는 시간이

최소한도  15분이 필요하죠

그러면 이 시간을 1분으로 하면 어떨까요.

연결된 컴퓨터들의 연결이 수시로 종료되겠죠.

컴퓨터 사용자들이 잠깐 화장실 갔다오기만 해도 연결이 종료되겠죠.

그러면 서버에 연결할수 있는 컴퓨터의 여유가 항상 어느정도 확보되겠죠.

수시로 서버컴에 연결하는 통로가 확보된다고 보면 되겠지요

연결이 끊긴다는 말이 크게 의미를 둘 필요는 없어요.

다시 작업을 시작한 순간  재연결되는 것이니까요


이 시간의 지정은 사용자께서 판단하시어 할 일이겠죠


실행창에서 cmd입력후 커맨드 창에서

ex) net config server /autodisconnect:1 ~5

 

시간은 1분이나 5분정도내에서 적당한 시간을 설정하시면 되겠네요

 

도움이 좀 되셨는지요.

내용출처 : 마이크로소프트의 고객지원센터
Posted by tornado
|
AX-1500G [MULTI EFFECT]




 AX-1500G [MULTI EFFECT]
 소비자가 298,000
 판매가250,000 원
 적립 포인트: 2,500 P
 구매수량
   
 제조원/원산지: KORG
 상품코드: L0703001

새로 출시된 TONEWORKS AX1500G는 56 개의 서로다른 이펙터와 훌륭한 stomp boxes 와 앰프, 그리고 speaker cabinets 의 효과를실제 장비처럼 재현하고, chorus, reverb, delay, pitch shift 같은 중요한 이펙터를 사용할 수 있습니다.

캐비넷 시뮬레이터는 총 11개가 내장되어 있습니다.(CABINET: 1X8 TWEED ・ 1X12 TWEED ・ 1X12 BLACK PANEL ・ 1X12 AC15 ・ 2X12 BLACK PANEL ・ 2X12 AC30 ・ 2X12 CLASS A ・ 4X10 TWEED ・ 4X12 CLASSIC ・ 4X12 VINTAGE ・ 4X12 MODERN)

Features: 48개의 프리셋과 한번에 8개까지 사용할 수 있는 멀티-이펙트 프로그램을 지원하며,채널-스위칭 앰프처럼 각 프로그램마다 두 개의 채널이 있습니다. Expression pedal로 실시간 이펙트 조정을 할 수 있고,아주 손쉬운 사용법으로 단지 몇 개의 노브를 사용해서 여러분이 원하는 사운드를 얻을 수 있습니다.

조명이 장착된 디스플레이로 스테이지에서 쉽게 볼 수 있습니다.

Phrase Trainer를 사용하여 여러가지 기타 리프를 쉽게 연습할 수 있고,Sample & Play 기능으로 어러분의 프레이즈나 리프를 레코딩하고 역방향으로 플레이할 수 있습니다.

Korg auto-chromatic tuner 와 metronome이 장착되어있고,KORG의 특허받은 REMS technology로 유명한 effects, amps and speaker cabinets의사운드를 실제적으로 제현합니다.

KORG REMS Technology

AX1500G는 KORG REMS technology를 사용하여 흘륭한 이텍트 사운드를 제공하여,The amp/distortion sounds는 따뜻한 느낌의 classic-tube overdrive부터 high-gain metal 사운드까지 모두 사용할 수 있습니다.

또한 spring reverb, tape echo 등등의 이펙터 사운드를 얻을 수 있고,

심지어 electric-acoustic 사운드를 모델링한 acoustic simulator를 사용할 수도 있습니다.

vintage 와 modern의 closed and open-back cabinet models은 4x12 stacks to 1x8 combos까지 표현할 수 있습니다.

Easy Editing

새로운 AX1500G는 복잡한 장비가 아닙니다.

ToneWorks design team은 훌륭한 사운드를 쉽고 빠르게 얻는 점을 바라고 있으며,

직간적인 구성으로 어떤 stomp box를 사용했던 기타리스트든지 쉽게 사용할 수 있습니다.

AX1500G는 직관적인 vintage-style 장비입니다. 96 Instantly Accessible Programs AX1500G는 48개의 프리셋 프로그램과 여러분이 만든 사운드를 저장할 수 있는 48개의 부가적인 프로그램이 제공됩니다.

하나의 프로그램에 8개 까지의 이펙터를 함께 사용할 수 있고,각각의 이펙터를 풋스위치로 켜고 끌 수 있습니다.

AX1500G의 독특한 점은 하나의 프로그램에서 기타리스트에게 두 가지의 채널을 지원한다는 것 입니다.

채널-스위칭 앰프처럼 바로 채널을 바꾸어서 솔로나 리듬 사운드를 사용할 수 있습니다.

Built in Expression Pedal offers Real-Time Control AX1500G는 wah, volume 그리고 pitch bend같은 이펙트를 실시간으로 조정할 수 있는 Expression pedal이 장착이 되어있습니다.

Expression pedal은 Sample & Play 기능에서도 사용되고,Sample & Play 기능은 여러분의 연주를 8초 까지 레코딩할 수 있는 기능이 있고,레코딩된 프레이즈를 루프해서 함께 연주할 수도 있고,역방향으로 플레이 할 수 도 있습니다.

Power-Paced Practise with the Phase Trainer

AX1500G는 아주 쉽게 리프를 연습할 수 있는 Phrase Trainer 기능을 가지고 있습니다.

여러분이 기타 솔로를 연습하길 원한다면 CD나 카세트에서 16초까지 레코딩해서 피치 변화없이 플레이 속도를 1/4로 천천히 프레이즈를 루프할 수 있습니다.

AX1500G는 AUX IN을 가지고 있어서 다른 오디오 소스와 함께 연주할 수 있습니다.

Auto Chromatic tuner

Korg는 처음으로 손에 들고 다닐 수 있는 electronic tuner를 개발한 이 분야의 선두주자입니다.

실제로 많은 기타리스트들이 Korg tuner를 사용하고 있고,AX1500G는 Bypass and Mute modes를 가지고 있는 auto-chromatic tuner가 장착되있어서,Mute mode로 무대위에서 소리없이 튜닝할 수 있습니다.

메트로놈도 가지고 있습니다.

Spec

-Programs: 96 (48 preset + 48 users)

-Effect variations: 56

-Rhythm: Metronome only

-Tempo: BPM40 - 208

-Sample and Play: 8.0 seconds

-Phrase trainer: 16.0 seconds

-Auto tuner -Assignable pedal: volume, wah, speed, depth,switch

-Foot switches: Ach/Bch Change, 1, 2, 3 and Bank Up


▷ 전 품목 50,000원 이상 구매시 무료배송 서비스를 제공해 드리고 있습니다.
(단, 일부 품목 및 지역 제외)

▷ 배송가능지역
- 전국이 가능(단, 일부 도서지역이나 해외는 따로 문의 바랍니다.)

제품 교환은 상품 도착후 3일 이내에 가능합니다.
제품이 이상있을 경우 5일 이내에 동일한 제품으로 교환이 가능합니다.
5일이후에 발생하는 소비자의 변심으로 인한 교환은 되질 않습니다.
특정상품에한하여 3일 이내에 포장 개봉이나 상품회손시 교환 불가능합니다.
-- www.akkishop.co.kr --

'이것저것 > 낙서장' 카테고리의 다른 글

파이트클럽 / 페르시아 왕자  (0) 2006.08.18
[뽀짜툰] 박스쟁탈전  (0) 2006.08.11
오늘 주문한책...  (0) 2006.07.12
루스 체인지 본 후에 검색해서 나온 사이트.  (0) 2006.07.09
사야쥐...  (0) 2006.06.26
Posted by tornado
|

언제 3, 4권이 나왔지...  

 

우리 땅에서 왜적을 토벌치 말라니 통분하옵니다 (이순신과 임진왜란 3)
지은이이순신역사연구회 지음 
출판사비봉출판사
가격
13,000원 → 최저가 10,400
//-->
출간일2006.05.15 | 450p | ISBN : 8937603349
평점 0(0건)
리뷰미디어리뷰(1건) | 네티즌리뷰(0건)

 

신에게는 아직도 열두척의 배가 남아 있나이다 (이순신과 임진왜란 4)
지은이이순신역사연구회 지음 
출판사비봉출판사
가격
13,000원 → 최저가 10,400
//-->
출간일2006.05.15 | 463p | ISBN : 8937603357
평점 0(0건)
리뷰미디어리뷰(1건) | 네티즌리뷰(0건)

 

'이것저것 > 낙서장' 카테고리의 다른 글

[뽀짜툰] 박스쟁탈전  (0) 2006.08.11
KORG AX-1500G 멀티 이펙터  (0) 2006.07.14
루스 체인지 본 후에 검색해서 나온 사이트.  (0) 2006.07.09
사야쥐...  (0) 2006.06.26
팔 부러졌음 ㅠㅠ  (0) 2006.06.22
Posted by tornado
|

http://www.aspire7.org/english/dark_28.html

 

 

프리메이슨은 또 뭐냐...

 

만화책 "신이라 불리운 사나이" 의 그 배후인가???

'이것저것 > 낙서장' 카테고리의 다른 글

KORG AX-1500G 멀티 이펙터  (0) 2006.07.14
오늘 주문한책...  (0) 2006.07.12
사야쥐...  (0) 2006.06.26
팔 부러졌음 ㅠㅠ  (0) 2006.06.22
놀러오세요  (0) 2006.04.20
Posted by tornado
|
출처 : www.sql-server-performance.com

작성자 : Randy Dyess

내용 : SQL2000 Table Hints

음음.. 여러가지.. SQL서버 쿼리의 힌트 들에 대한 정보 입니다.

참고 하시길 바랍니다.




 
SQL Server 2000 Table Hints








 
by Randy Dyess

Visit his website at: www.TransactSQL.com

 

As you advance in your skills as a Transact-SQL developer, or SQL Server database administrator, there will come a time when you need to override SQL Server's locking scheme and force a particular range of locks on a table. Transact-SQL provides you with a set of table-level locking hints that you can use with SELECT, INSERT, UPDATE, and DELETE statements to tell SQL Server how you want it to lock the table by overriding any other system-wide or transactional isolation levels.

This article will describe the use of the table-level locking hints and general table hints that are available to Transact-SQL developers and SQL Server database administrators, and attempt to provide scenarios on when you should use a particular hint. You should note that SQL Server's query optimizer will automatically determine what it thinks is the best type of lock to use on an object in a query, and you should only override this choice only when necessary.

After saying that, it is sometimes necessary to correct the optimizer and use a hint to force the optimizer to use an index other than the one it picks, or to simply control the behavior of the locks. An example of choosing an alternative index would be when the query optimizer chooses an index that is constantly out of date and you do not have the cycles to bring the index up to date before you run the query. An example of controlling the locking behavior would be to lock a table to optimize a BULK INSERT.


Table Hints May Not Always Be Used By the Query Optimizer
You should note that even though you specify a table-level hint in your code, the query optimizer may ignore the hint. Table-level hints will be ignored if the table is not chosen by the query optimizer and used in the subsequent query plan.

In addition, the query optimizer will often choose an indexed view over a table. In case your table-level hint will be ignored, you can override the query optimizer's preference for indexed views by using the OPTION (EXPAND VIEWS) query hint.

Another reason the query analyzer may ignore your hint is due to the fact that the table may contain computed columns and the computed columns are computed by expressions and functions referencing columns in other tables, and the table hints are not specified for those tables. Table hints are not propagated on tables with computed columns, so the hint will not be used on tables referenced by computed columns, table-level hints are propagated on base tables and views referenced by another view though.

SQL Server also does not allow more than one table hint from either the Granularity hint group (PAGLOCK, NOLOCK, ROWLOCK, TABLOCK, TABLOCKX), or the Isolation Level hint group (HOLDLOCK, NOLOCK, READCOMMITTED, REPEATABLEREAD, SERIALIZABLE) to be used in the FROM clause for each table. This basically means that you cannot specify ROWLOCK and TABLOCK for a table in the same FROM clause. SQL Server will also not allow the NOLOCK, READUNCOMMITTED, or READPAST hints to be used against tables that are the targets of a DELETE, INSERT or UPDATE statement.


Table Hint Syntax
Now that we have mentioned most of the hints, let's look at the syntax for table-level hints used with the FROM clause.

SYNTAX[ FROM { < table_source > } [ ,...n ] ] < table_source > ::= table_name [ [ AS ] table_alias ] [ WITH ( < table_hint > [ ,...n ] ) ] < table_hint > ::= { INDEX ( index_val [ ,...n ] ) | FASTFIRSTROW | HOLDLOCK | NOLOCK | PAGLOCK | READCOMMITTED | READPAST | READUNCOMMITTED | REPEATABLEREAD | ROWLOCK | SERIALIZABLE | TABLOCK | TABLOCKX | UPDLOCK | XLOCK } Microsoft encourages the use of the WITH keyword, even though it is optional, as they state that a future release of SQL Server may require this keyword. Microsoft also encourages the use of the optional commas between different hints, as spaces are only allowed for backward compatibility reasons.

You can see that there are fifteen hints defined in this syntax listing. Thirteen of these hints (HOLDLOCK, NOLOCK, PAGLOCK, READCOMMITTED, READPAST, READUNCOMMITTED, REPEATABLEREAD, ROWLOCK, SERIALIZABLE, TABLOCK, TABLOCKX, UPDLOCK, XLOCK) are considered table-level locking hints while (INDEX and FASTFIRSTROW) are considered table hints. This doesn't mean much to most developers, but I thought I would tell you how Microsoft groups them.


Table Hint Descriptions
Now that you know the names of the hints, how they are grouped, and the syntax of each, lets go over what each hint does.


INDEX is used to specify the name or object ID of an index or indexes that will be used by SQL Server when processing the statement. SQL Server will chose an index by default if one is not specified by the use of the INDEX keyword, but sometimes you will need to force SQL Server to use a particular index.

Only one index hint can be used per table, but you can specify more than one index in this hint. If a clustered index exists on the specified table, using INDEX(0) will force a clustered index scan and INDEX(1) will force a clustered index scan or seek. If no clustered index exists on the table, then INDEX(0) will force a table scan while INDEX(1) will be interpreted as an error.

If you chose multiple indexes to be used for the hint, any duplicates will be ignored. Be careful in the order you place indexes when you use multiple indexes with the index hint. SQL Server try to apply as many conditions as possible on each index, so if you place the broader indexes first, you may have all your conditions covered and SQL Server will not have to create AND statements for all the specified indexes.

You can use a maximum of 250 non-clustered indexes in an index hint. Be aware that if an index hint with multiple specified indexes is used on a fact table in a star join, then SQL Server will ignore will return a warning message and ignore the hint.


FASTFIRSTROW will optimize the query to retrieve the first row of the result set.


HOLDLOCK (equivalent to SERIALIZABLE) applies only to the table specified and only for the duration of the transaction, and will hold a shared lock for this duration instead of releasing it as soon as the required table, data page, row or data is no longer required. HOLDLOCK cannot be used in a SELECT statement with the FOR BROWSE option specified.


NOLOCK (equivalent to READUNCOMMITTED) permits dirty reads. Dirty reads will not issue shared locks and will ignore exclusive locks placed by other processes. It is possible to receive error messages if the read takes place on an uncommitted transaction or a set of pages being rolled back.


PAGLOCK will force the use of a page lock instead of a table lock.


READCOMMITTED specifies that shared locks are held while the data is being read to avoid dirty reads, but the data can be changed before the end of the transaction, which will result in nonrepeatable reads and may cause phantom data. READCOMMITTED is the default table hint in SQL Server.


READPAST specifies that locked rows be skipped during the read. READPAST only applies to transactions operating at the default READ COMMITTED isolation level, and will only read past row-level locks. READPAST can only be used in SELECT statements. Normal blocking can be worked around by having transactions read past rows being locked by other transactions.


READUNCOMMITTED (equivalent to NOLOCK)  permits dirty reads. Dirty reads will not issue shared locks and will ignore exclusive locks placed by other processes. It is possible to receive error messages if the read takes place on an uncommitted transaction or a set of pages being rolled back.


REPEATABLEREAD specifies that locks be placed on all data that is used in a query, preventing other users from updating the data, but new phantom rows can be inserted into the data set by another user and are included in later reads in the current transaction.


ROWLOCK forces the use of row-level locks instead of page or table level locks.


SERIALIZABLE (equivalent to HOLDLOCK) applies only to the table specified and only for the duration of the transaction, and it will hold a shared lock for this duration instead of releasing it as soon as the required table, data page, row or data is no longer required.


TABLOCK specifies that a table lock to be used instead of a page or row level lock. This lock will be held until the end of the statement.


TABLOCKX specifies that an exclusive lock be held on the table until the end of the statement or transaction, and will prevent others from reading or updating the table.


UPDLOCK specifies that update locks will be used instead of shared locks, and will hold the locks until the end of the statement or transaction.


XLOCK specifies that an exclusive lock be used and held until the end of the end of the transaction on all data being processed by the statement. The granularity of XLOCK will be adjusted if it is used with the PAGLOCK or TABLOCK hints.


Table Hint Usage
Now that you know a little about each of the table-level hints, you may be wondering when you may need to use them. Where I work, we have a very large database that is used by approximately 10,000 customer service reps in a call center environment. While the reps are using the database, we have to load approximately 400,000 new rows of data into the database every three days. This load process can take up to 16 hours, so we are often forced to run the load during operational hours.

To optimize our BULK INSERT load process, we have added the TABLOCK hint to lock tables and speed inserts, and the READUNCOMMITTED hint to allow dirty reads of the data. All transactions generated by the reps are placed into smaller transactional databases so dirty reads are not a problem.

Our very large database and large number of monthly inserts caused our table statistics and indexes to be out of date. We just didn't have enough operating cycles to keep the all of the statistics and indexes completely updated after every data load.

This problem sometimes caused the query optimizer to create incorrect query plans because it did not always have the most up-to-date information, resulting in poor performance. This forced me to use index hints to force a query to use an index or indexes that I knew were keep updated to solve the slow response times.

Another use of the index hint is to force the use of an index when the query optimizer insists on using a table scan. For example, the SQL Server 7.0 query optimizer seems to have a preference for table scans even though very few rows of the table will be returned by the query.

I don't tend to use the many other hints at work, but in the past I have found use for the READPAST hint in work queues to allow a row of data to be returned to a client without waiting for locks to be releases by other processes. This is nice to use if you do not want end users to obtain the same row of data.

Others have told me that they often use the FASTFIRSTROW hint when they want to return the first row to the user quickly, to give them something to do, while the rest of the query catches up. I haven't found too many uses for TABLOCKX, UPDLOCK, XLOCK, or SERIALIZE (HOLDLOCK) in the type of databases I'm accustomed to working with, but I have been told that they are great hints for financial and reporting situations when you need the data to be consistent throughout a transaction.

Different hints are needed for different types of databases or transactions, and you will eventually determine which ones are proper for your situation.


Summary
As you can see, table-level hints are available for use by Transact-SQL developers or SQL Server database administrators, but should only be used to fine-tune your code, not as a standard technique for writing queries. You should perform a strict review of the query plans procedure by the query optimizer before you decide that a table-level hint may be want you need to solve your problem. In addition, you should perform this strict review after the hint is in place.

While table-level hints are not for all levels of users, experienced administrators and developers can use them to solve a limited set of problems, as well as fine-tune a limited set of queries in which the query optimizer has failed in its job to optimize correctly.


Knowledge Based Articles
Q235880 INF: Optimizer Hint NOLOCK or Isolation Level READ UNCOMMITTED Generates Error 605
Q297466 BUG: READPAST Locking Hint Returns an Incorrect Number of Rows
Q308760 FIX: SQL Server Optimizer Ignores Index Hint for UPDATE If One or More Non-Clustered Indexes Exist
Q308886 PRB: NOLOCK Optimizer Hint May Cause Transient Corruption Errors in the SQL Server Error Log
Q310935 FIX: Use of a Dynamic API Server Cursor with a NOLOCK Hint Causes Error 1047
Q320434 FIX: Bulk Insert with TABLOCK Hint May Result in Errors 8929 and 8965 When You Run CHECKDB
Q247365 BUG: Dynamic Cursor With NOLOCK Hint, DELETE Activity, Causes Assertions in Error Log

Posted by tornado
|

SELinux의 이해

OS/LINUX 2006. 7. 4. 11:53

Fedora Core4에 기본 포함된 Selinux에 대한 개념이해하는데 많은 도움이 될 수 있는 문서입니다.

 

 

1. SELinux의 이해

Q: SELinux란?
Q: SELinux 정책이란?
Q: SELinux 목표 정책(SELinux targeted policy)이란?
Q: 어떤 데몬이 목표 정책에 의해 보호받는가?
Q: 어느 데몬을 목표 정책에 추가할 것인가? Sendmail, Postfix, MySQL, 혹은 PostgreSQL?
Q: 염격한 정책은 어떤가? 이 정책 조차도 유효한가?(Does it even work?)
Q: 파일 문맥이란?
Q: 파일, 사용자, 프로세스의 보안 문맥을 확인하는 방법은?
Q: 영역과 유형은 어떻게 다른가?

 

2. SELinux 제어하기

Q: SELinux 설치 및 설치 안하는 방법은?
Q: 사용중인 정책을 교체하는 방법은?
Q: 목표 정책하에서 특정 데몬에 대하여 SELinux protection을 활성화/비활 성화 방법은?
Q: 부팅시 SELinux를 비활성화시키는 방법은?
Q: 부팅시 enforcing을 활성화/비활성화하는 방법은?
Q: 재부팅하지 않고 enforcing 모드를 임시로 비활성화시키는 방법은?
Q: 부팅시 시스템콜 auditing 키거나 끄는 방법은?
Q: 재부팅을 하지않고 시스템콜 auditing을 잠정적으로 끄는 방법은?
Q: SELinux 설치에 관한 상태 정보(status info)를 얻는 방법은?

 

3. 문제 해결하기

Q: 응용프로그램이 기대했던 데로 동작하지않고 avc: denied 란 메시지가 나타나면, 어떻게 이 문제를 해결하는 가?
Q: 기존 /home 파티션이 있는 시스템에 휘도라 코아를 설치하고 로그인을 할 수 없을 때 해결방법은?
Q: setfiles나 fixfiles를 사용하여 /home을 재명명한 후, 여전히 SELinux 비활성 시스템(non-SELinux-enabled system)으로 /home을 읽을 수 있을까?
Q: 휘도라 코아와 비SELinux 시스템간에 NFS를 사용하여 디렉토리를 공유하는 방법은?
Q: 적절한 문맥을 갖는 사용자 홈 디렉토리와 함께 새 리눅스 사용자 계정 을 만드는 방법은?
Q: 다른 모든 SELinux 문서는 su이 단지 리눅스 정체성만을 바꾸고 보안 역할(security role)은 아니라고 말한다.
Q: 특정 프로그램에 대한 로그를 채우는 avc 오류에 골치를 앓고 있다. 어떻게 하면 그것에 대한 접근을 감시하지(audit) 않도록 선택할 수 있는가?
Q: 비록 허가 모드에서 운행될 지라도(even running in permissive mode), 많은 수의 avc denied 메시지가 나타난다.
Q: 오직 SELinux가 enforcing 모드에 있을 때만 특정 허가 거부를 받지만, /var/log/messages에는 어떠한 감시 메시지를 볼 수가 없다. 이들 침묵의 거부(silent denials)의 원인을 밝혀낼(identify) 수 있는 방법은?
Q: 정책 패키지를 업그레이드할 때(예를 들어, yum을 사용하여), 기존 정책 에 어떤 일이 발생하는가; 자동으로 업데이트되는가?
Q: 만일 응용프로그램 패키지와 함께 보급되는 정책이 재명명이 필요한 방법으로 변경된다면, RPM은 패키지가 소유한 파일들을 재명명을 처리할 것인가?
Q: 정책과 정책 소스 패키지사이에 어떤 관계가 있는가?
Q: 왜 /etc/selinux/policyname/policy/policy.<version>과 /etc/selinux/policyname/src/policy/policy.<version> 파일은 다른 (크기, md5sums, 날짜)를 갖는가?
Q: 새로운 정책 패키지가 시스템을 비활성화시킬(disable) 것인가?
Q: 정책 작성에 도움을 줄 수 있는 방법은?
Q: 콘솔에 메시지가 넘쳐나고 있다. 어떻게 이것을 막아낼 수 있는가?
Q: 정책 소스를 설치하지 않고 기본 정책을 시험할 수 있는가?
Q: KDE 응용프로그램을 SELinux하에서 작동하는 데 문제가 있다.
Q: SELinux=disabled가 작용하지 않는 이유는?

 

4. SELinux 배치하기

Q: SELinux를 사용하기 위해 어떤 파일 시스템을 선택해야 하는가?
Q: SELinux는 시스템 성능에 어떠한 영향을 미치는가?
Q: SELinux를 효과를 제고하기위해(to leverage SELinx in) 첫째로 보아야 할 것은 어떤 유형의 배치/응용프로그램/시스템 등 인가(What types of deployments/applications/systems, etc.)?
Q: 어떻게 SELinux가 제삼 응용프로그램에 영향을 끼치는가?

 

문서출처 : KLDP

Posted by tornado
|

상품소개



 

 

 

국내최대의 기타 브랜드 Cort사의 2006년을 겨냥한 새로운 라인업 EVL 씨리즈중 EVL - K4 일랙트릭 기타입니다. 마호가니 바디와 하드메이플넥, 로즈우드 지판, EMG HZ H4 픽업장착 그리고 무광 블랙 피니쉬!! 디자인만 봐도 강력한 사운드가 느껴지는 기타입니다.

 

 

 

 

 

 

 

 

 

 

 



솜 빵빵한 소프트케이스 및 스쿨뮤직 악세사리 세트 포함!

 

 

 

 

 

 

 

Model Name

 

EVL - K4

Body

 

Mahogany

Neck

 

Hard Maple

Fingerboard

 

Rosewood

Scale

 

25 1/2" 24F

Construction

 

Bolt - On neck joint

Pickups

 

EMG HZ H4 ( Bridge)

EMG HZ H4 (Neck)

Tuners

 

Die Cast

Bridge

 

Double Locking III Tremolo

Hardware Color

 

BKS (무광)

Color

 

BKS (무광)

Posted by tornado
|

NTLDR is missing

Press any key to restart

 

NTLDR파일은 XP의 시스템파일중 하나 이다. 그렇기 때문에 손상되었거나 없으면

부팅이 않되면서 위와 같은 메세지가 나온다.

 

이런 메세지로 인해 부팅을 할 수 없을 경우에는 XP씨디에 있는 복구콘솔 프로그램을 이용하여

해결한다.

 

# 문제 원인

   NTLDR, BOOTFOT.BIN, NTDETDCT.COM, BOOT.INI 파일을 실수로 지웠을 경우

 

# 해결 방법 복구콘솔(XP 설치씨디에 있다)

1. COPY 명령으로 NTLDR 파일 복구

2. FIXBOOT 명령으로 BR 영역 보구

3. COPY 명령으로 BOOTFONT.BIN과 NTDETECT.COM파일 복구

 

# XP설치씨디를 이용하여 복구콘솔로 복구하는 방법

1. XP설치씨디를 씨디롬에 넣는다.

2. 컴퓨터를 재부팅한다.

3. 재부팅과 동시에 F2키나 DEL키를 계속 눌러서 CMOS SETUP으로 들어간다.

4. BOOT SEQUENCE로 들어가 부팅순서를 CDROM이 첫번째로 되게 설정한다. : BIOS에 따라 다름

5. F10키를 누른후 저장하고 재부팅

6. CD-ROM으로 부팅이 되면 R(복구콘솔)을 눌러 복구콘솔로 들어간다.

7. 키보드 선택시 첫번째 선택

8. 로그온할 WINDOWS 설치를 선택하십시오. 에서 1입력

9. 암호는 대부분 설정을 안하셨을텐 그냥 ENTER

10. C:WINDOWS

                여기 부터가  복구콘솔 명령을 실행할 수 있는 화면이다.

                띄어쓰기를 잘 해야 하는데 편의상 ^로 하겠다.(절대로 같이 표기하지 말것)

                씨디롬 드라이브가 D: 라고 가정한다.

11. CD ^

12. COPY^D:I386NTLDR^C:

13. FIXBOOT

14. COPY^D:I386BOOTFONT.BIN^C:

15. COPY^D:I386NTDETECT.COM^C:

16. EXIT

17. 자동으로 재부팅

Posted by tornado
|

왼팔 부러졌음 ..;

 

오른팔 아닌게 다행이다.

 

다음주에 경과보구 수술할지 결정. ㅜㅜ

Posted by tornado
|

분산파일 시스템

OS/WIndows 2006. 6. 21. 18:12

DFS(분산파일 시스템)

1. 개요
Windows 2000 Server 분산파일 시스템은 네트워크의 사용자들이 네트워크에서 파일을 찾고, 보고, 편집하는 것을 용이하게 한다. 이것은 DFS가 중앙 위치에서 네트워크의 어느 컴퓨터상의 파일에나 사용자가 액세스 하도록 하기때문이다.
DFS를 설치할 때는, DFS 루트-파일 및 파일

2. 분산파일 시스템이란?
Microsoft Distributed File System은 기업에 있는 여러 유형의 파일 시스템 리소스에 대해 하나의 이름 공간을 구현한다. Dfs는 물리적 리소스와는 독립된 하나의 논리적 트리 구조로 구성된다. Dfs 트리 토폴로지는 Directory 서비스에 자동으로 게시되어 Dfs 루트의 내결함성을 구현한다.
사용자가 Dfs 루트에 추가하는 볼륨은 공유 네트워크 디렉터리를 나타내는 리프 또는 분기 노드에 해당한다. 공유 리소스는 단일 트리나 복수의 Dfs 트리를 사용하여 분산될 수 있다. 그룹 액세스 권한과 같은 표준 Windows 2000 Server 보안 기능을 사용할 경우 Dfs 볼륨에 대한 액세스가 제한될 수 있다.
Dfs 트리는 하나의 DNS 이름 공간이다. 따라서 Dfs 볼륨에 대한 DNS 이름은 Dfs 루트의 호스트 서버를 확인해 준다. Active Directory는 하나의 Dfs 트리에 대한 여러 호스팅 서버 간의 볼륨 참조를 중재한다.
Dfs 트리는 사용자에게 적절한 네트워크 리소스에 대한 통일되고 가시적인 액세스 방법을 제공한다. 참조되는 리소스의 기존의 하위 디렉터리는 앞의 예에 나온 C++ 및 Java 하위 디렉터리의 경우처럼 상위 디렉터리와 함께 Dfs에 게시된다. Dfs 클라이언트 모듈은 Windows 2000 Server 및 Professional에 자동으로 설치되는 SMB(Server Message Block) 프로토콜에 기본적으로 제공된다.

3. DFS 요구 사항

플랫폼
호스트 DFS 클라이언트
호스트 DFS 루트
DOS, Windows3.x, Windows for Workgroup 및 NetWare 서버 아니오 아니오
Windows 95 예 - DFS 4.x 및 5.0용
클라이언트 다운로드
아니오
Windows 98 예 - DFS 4.x 및 5.0(독립형) 클라이언트 포함 및 DFS 5.0(도메인 기반)용 클라이언트 다운로드 아니오
Windows NT4.0 및
서비스 팩 3
예 - DFS 4.x 및 5.0(독립형) 클라이언트 포함 예 - 독립형 서버 전용
Windows 2000 DFS 5.0 클라이언트 포함 예 - 독립형 및 도메인 기반 서버 또는 도메인 컨트롤러

4. DFS 루트 만들기

1) 분산 파일 시스템을 시작한다. (시작-프로그램-관리도구-분산 파일 시스템)


2) 분산 파일 시스템에서 오른쪽 클릭후, 새 DFS 루트를 선택한다.


3) 새 DFS 루트 마법사가 나타나고, “다음”에 클릭한다.


4) 다음 스크린은 DFS 루트의 결함허용의 추가적인 옵션 사항이다. 이것은 액티브 디렉토리를 사용하여 정보를 저장한다. 그리고 액티브 디렉토리를 사용할 수 없을 때나 원하지않으면 DFS 루트 자체를 저장한다. “도메인 DFS 루트 만들기”를 선택한다. 그리고 다음을 클릭한다.


* 도메인 DFS 루트 만들기와 독립 실행형 DFS 루트 만들기와 차이점
도메인 기반 DFS 루트가 Active Directory를 사용하고 독립형은 그렇지 않은 것 이외에도 도메인 기반 루트는 도메인 멤버 서버에 설치해야 하며, 루트 디렉토리에 공유폴더를 가질 수 있고 여러 수중의 DFS 연결을 가질 수 있다. 독립형 루트는 제한된 연결 계층 구조를 가지며 루트 수준 공유 폴더를 가질 수 없다.

5) DFS 루트에 대한 호스트 도메인을 선택해야 한다. ( 결함허용일 때는 도메인 번호) 그리고, DFS 서비스를 실행해야 한다. 현재의 서버가 선택 되어질 것이나, 도메인 이름을 타이핑 하거나 브라우저를 클릭하여 바뀐다. 다음을 클릭한다.





6) 다음은 DFS 루트 볼륨을 위한 선택 사항이다. 크게 두개의 옵션이 있다.




7) 각각의 DFS 루트는 고유 이름이 필요하며, 이름을 바꾼다 할지라도 디폴트(default)로서 할당량의 이름이된다. 그리고, 새로운 DFS를 최근의 제어 테이블(console)에 추가할 수 있다. “다음”을 클릭 한다.


8) 도메인, 서버 그리고 할당의 이름이 요약 되어 있고, “마침”에 클릭한다.


9) 마침 후 화면 입니다.

Posted by tornado
|

휴지통까지 비웠을때,

shift + delete 로 파일 지웠을때,


복구 해야할때 유용함 ㅋㅋ

Posted by tornado
|
Posted by tornado
|
Posted by tornado
|
Core Java Technologies Technical Tips
 Core Java Technologies Tech Tip에 오신 여러분을 환영합니다
Core Java Technologies
TECHNICAL TIPS
2006년 2월 8일자
 이번 호에서는,

» Singleton 패턴
» Observer 패턴

을 다룹니다.

이 문서는 Java 2 Platform, Standard Edition Development Kit 5.0 (JDK 5.0)을 기반으로 개발되었습니다. PDF 파일받기    

Singleton 패턴
 

설계 패턴은 소프트웨어 설계에서 상에서의 공통 문제에 대한 일반적인 솔루션이라 할 수 있는데, 그 기본 개념은 솔루션을 코드로 변환하면 그 코드를 다양한 문제 상황에 적용할 수 있다는 것이다. 설계 패턴에 관한 논의는 Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides 등이 공동 집필한 Design Patterns: Elements of Reusable Object-Oriented Software에서 시작되었다. 이 책에서는 패턴을 생성, 구조, 동작의 세 가지 주요 영역이 포함하여 다양한 주제 영역으로 분류하고 있다. 생성 패턴(Creational patterns)은 객체가 생성되는(객체 지향 용어로는 ‘예시되는(instantiated)’) 방식을 기술한다. 구조 패턴(Structural patterns)은 객체들을 연결하고 결합하는 방식을 도와주고, 동작 패턴(Behavioral patterns)은 알고리즘 또는 통신 메커니즘을 기술한다. 몇 가지 공통 패턴의 이름으로는 생성 영역의 Singleton, 동작 영역의 Observer, 구조 영역 Facade를 들 수 있다. 본 테크 팁에서는 자바 프로그래밍 언어의 맥락에서 Singleton 패턴을 면밀히 살펴보도록 한다.

Singleton 패턴은 흔히 사용되는 생성 패턴의 하나이다. 이는 하나의 클래스에서 오직 하나의 인스턴스만 생성되도록 보장하는 기법을 기술한다. 이는 본질적으로, 클래스 외부의 누구도 객체의 인스턴스를 생성하지 못하게 하는 접근법을 사용한다. 일반적으로 Singleton은 느리게 생성되어 필요 시점까지 메모리의 요구를 줄여준다. 이 접근법은 다양한 방식으로 구현이 가능하다.

생성되고 있는 하나의 인스턴스가 서브클래스가 되리라는 것을 알고 있다면, 상위(parant) 클래스를 추상화하고 메소드를 제공하여 현재의 인스턴스를 얻도록 한다. 그 일례로 AWT 패키지의 Toolkit 클래스를 들 수 있으며, Toolkit을 위한 생성자는 public(이 특정 경우에는 디폴트 생성자)이다.
public Toolkit()그리고 클래스는 특정 서브클래스(이 경우에는 플랫폼을 따름)를 얻기 위한 getDefaultToolkit() 메소드를 가진다.
public static Toolkit getDefaultToolkit()썬 자바 런타임을 탑재한 Linux 플랫폼 상에서 특정 서브클래스는 sun.awt.X11.XToolkit 타입이다. 하지만 사용자는 공통 추상 상위 클래스인 Toolkit을 통해 클래스에 액세스할 뿐이므로 이 부분까지 알아야 할 필요는 없다.

Collator 클래스는 이 패턴의 또 다른 예로, 약간의 차이가 있다. 이 클래스는 2개의 getInstance() 메소드를 제공하고, 무인자(no-argument) 버전은 디폴트 locale을 위한 Collator를 얻는다. 이 때, 사용자는 자체 locale을 전달하여 해당 locale을 위한 Collator 인스턴스를 얻을 수 있다. 동일 locale에 대한 Collator를 여러 차례 요청해도 동일한 Collator 인스턴스를 돌려받게 되며, 생성자 자체는 보호된다. 한편, J2SE 표준 라이브러리 전반에 걸쳐 클래서 생성을 제한하는 유사한 방식을 발견할 수 있다.

이 시점에서 클래스 생성자에 대한 액세스를 제한하면 자동적으로 Singleton이 된다고 생각할 수도 있겠으나, 그렇지 않다. 문제가 되는 케이스는 Calendar 클래스인데, Calendar 클래스 생성자는 보호되며, 이 클래스는 클래스 인스턴스를 얻기 위한 getInstance() 메소드를 제공한다. 그러나 getInstance() 메소드를 호출할 때마다 새로운 클래스 인스턴스가 얻어짐으로 결국 이는 Singleton이 아닌 것이다.

사용자의 자체 Singleton 클래스 생성 시에는 오직 하나의 인스턴스만 생성되도록 유의해야 한다.
public class MySingleton { private static final MySingleton INSTANCE = new MySingleton(); private MySingleton() { } public static final MySingleton getInstance() { return INSTANCE; } }정적 메소드 getInstance()는 단일 클래스 인스턴스를 리턴한다. 단일 인스턴스가 서브클래스일 필요가 있더라도 API를 변경할 필요는 없다는 점에 주목할 것.

이론적으로는 INSTANCE 변수가 public일 수 있으므로 getInstance() 메소드는 필요치 않으나 getInstance() 메소드는 향후에 시스템을 변경할 경우 유연성을 제공한다. 바람직한 가상 머신 구현이라면 정적 getInstance() 메소드에 대한 호출을 즉시 처리(inline)해야 한다.

Singleton 생성 작업은 이것으로 그치지 않는다. 즉, Singleton 클래스를 Serializable로 만들 필요가 있다면 반드시 readResolve() 메소드를 제공해야 한다.
/** * Ensure Singleton class */ private Object readResolve() throws ObjectStreamException { return INSTANCE; }readResolve() 메소드가 갖추어진 상태에서 deserialization은 단일(오직 하나의) 객체(getInstance() 메소드에 대한 호출에 의해 생성되는 것과 동일한 객체이다)로 귀결되는데, 사용자가 readResolve() 메소드를 제공하지 않을 경우에는 객체를 deserialize할 때마다 객체 인스턴스가 생성된다.

Singleton 패턴은 오직 단일한 리소스만 가지고 있고 그 단일 리소스의 상태 정보에 대한 액세스를 공유할 필요가 있음을 알고 있을 경우에 유용하다. 설계 시에 Singleton 패턴의 필요성을 파악하면 개발을 간소화할 수 있다. 하지만, 때로는 성능 문제로 코드를 refactor하고 나중에 패턴을 사용하게 되기까지 필요성을 인식하지 못하는 수가 있다. 예를 들어, 프로그램이 동일한 클래스의 인스턴스를 반복 생성하여 상태 정보와 함께 전달하기 때문에 시스템 성능이 저하되는 경우가 발생할 수 있다. Singleton 패턴으로 변경하면 동일한 객체가 반복되는 것을 방지할 수 있는데, 이는 시스템이 객체를 재생성하는데 드는 시간을 제거해줄 뿐 아니라 garbage collector가 인스턴스들을 삭제하는 데 소요되는 시간을 줄여준다.

간단히 말해서, 단일의, 그리고 오직 하나의 클래스 인스턴스만 생성되도록 하고자 할 때 Singleton 설계 패턴을 이용하면 된다. 생성자가 연산을 요구하지 않을 경우에는 빈 private 생성자(또는 서브클래스가 필요할 경우에는 보호된 생성자)를 제공한다. 그렇지 않으면 디폴트값으로 시스템이 public 생성자를 제공하게 되는데, 이는 Singleton으로 작업 시 바람직하지 않은 결과라 할 수 있다.

Singleton은 주어진 클래스 로더 내에서만 고유성이 보장된다는 점에 유의할 것. 복수의 서로 다른 엔터프라이즈 컨테이너에 걸쳐 동일한 클래스를 사용할 경우에는 각 컨테이너에 대해 하나의 인스턴스를 얻게 된다.

Singleton 패턴은 종종 Factory 패턴이라 불리는 다른 패턴과 함께 사용되는데, Factory 패턴도 Singleton 패턴과 마찬가지로 생성 패턴의 일종이다. 이 패턴은 특정 객체의 서브클래스, 또는 보다 일반적으로 특정한 인터페이스의 구현이 어떻게 실제로 객체를 생성하는지 기술한다. Factory 패턴의 좋은 보기로 Swing BorderFactory 클래스를 들 수 있다. 이 클래스는 다양한 종류의 Border 객체를 리턴하는 일련의 정적 메소드를 가지는데, 서브클래스의 구현 세부사항을 숨겨서 factory가 인터페이스 구현을 위한 생성자를 직접 호출할 수 있게 해준다. 다음은 BorderFactory의 사용 예제이다.
Border line = BorderFactory.createLineBorder(Color.RED); JLabel label = new JLabel("Red Line"); label.setBorder(line);여기서 BorderFactoryLineBorder를 생성한다는 사실이나 그 생성 방법은 숨겨져 있다. 이번 특정 예제에서는 LineBorder 생성자를 직접 호출할 수 있지만 Factory 패턴을 이용하는 대부분의 경우에는 직접 호출이 불가능하다.

Singleton 패턴을 구현하는 클래스는 다른 클래스의 인스턴스를 생성하기 위해 Factory로 사용할 객체를 리턴하는 경우가 흔히 있는데, 이는 PopupFactory 클래스에 의한 Popup 객체 생성 방식에 의해 예증된다.

Singleton factory를 얻으려면 PopupFactorygetSharedInstance() 메소드를 호출한다.
PopupFactory factory = PopupFactory.getSharedInstance();그런 다음 factory의 getPopup() 메소드를 호출하여 factory에서 Popup 객체를 생성하고, 상위 컴포넌트, 그 콘텐츠, 포지션을 전달한다.
Popup popup = factory.getPopup(owner, contents, x, y);보안 컨텍스트에서 Factory 패턴이 자주 사용되는 것을 볼 수 있을 것이다. 다음 예제에서는 특정 알고리즘에 대한 certificate factory를 획득한 다음 stream certificate를 생성한다.

FileInputStream fis = new FileInputStream(filename); CertificateFactory cf = CertificateFactory.getInstance("X.509"); Collection c = cf.generateCertificates(fis);BorderFactory에서 본 것처럼, Factory 패턴이 반드시 Singleton 패턴과 함께 사용되어야 하는 것은 아니지만 실제로는 두 패턴이 함께 사용되는 경우도 종종 볼 수 있다.

맨 위로

Observer 패턴
 

앞서 다룬 Singleton 패턴과 마찬가지로, Observer 패턴은 자바 프로그램에서 많이 사용되는 설계 패턴이다. 이 패턴은 동작 설계 패턴으로, 클래스가 느슨하게 연결되는 방식과 타 클래스 업데이트 시 하나의(또는 다수의) 클래스가 통지되는 방식을 정의한다. 기본적으로, 이는 특정 장소에서 무슨 일이 발생할 경우, 이를 보고있었거나 관심을 가지고 있던 사람들에게 상황을 통지하는 것을 의미한다.

Observer 패턴을 취급하는 방식에는 두 가지가 있는데, 첫 번째 방식은 java.util package에서 볼 수 있는 ObserverObservable 클래스를 수반하는 것이고, 두 번째 방식은 컴포넌트에 이벤트 리스너를 등록하는 JavaBeans 컴포넌트 모델을 따르는 것이다.

JavaBeans 이벤트 모델 생성에 앞서 ObserverObservable 클래스는 Observable 패턴의 구현을 기술한다. 달리 말해서 이 클래스들은 Java 플랫폼 1.0 버전 때부터 사용되어 왔고, 기술적으로 하자가 없었으며 여전히 라이브러리에 존재하고 있는 것이다. 또한, 이 클래스들은 여전히 Observable 패턴 구현에 사용할 수는 있지만, 두 번째 모델인 JavaBeans 컴포넌트 모델이 일반적으로 사용된다. Observable 패턴 구현을 위해 이 클래스들을 사용하는 데 따른 한 가지 중요한 문제는 Observable 확장이 필요하다는 점인데, 이 경우 자바 플랫폼의 단일 상속 세계에서는 불가능할 수도 있는 클래스 하이어라키 구조를 강요 받게 된다.

이벤트 리스너를 등록하는 JavaBeans 컴포넌트 모델은 일련의 add 및 remove 메소드를 수반하는데, 여기서 리스너 타입은 메소드 이름에 내장되어 있다. 예를 들어, 버튼의 선택을 관찰하기 위해서는 컴포넌트에 ActionListener를 등록한다.
ActionListener listener = new ActionListener() { public void actionPerformed(ActionEvent actionEvent) { ... } }; JButton button = new JButton("Pick Me"); button.addActionListener(listener);시스템 정의 클래스를 위한 Observer 패턴은 이것이 전부라고 할 수 있는데, 리스너 인터페이스를 구현하고, 그것을 관찰 Subject에 첨부한 다음 기다린다. Subject는 관찰되는 대상으로, 누가 관찰하고 있는지를 기억하는 일을 책임진다. JavaBeans 컴포넌트 모델의 경우, Observer 객체를 첨부, 분리하기 위한 인터페이스로 add/remove 리스너 네이밍 패턴이 사용된다. Subject의 상태가 변경되면 이를 Observer 객체에 통지한다.

패턴의 주된 목표 중 하나는 Subject와 Observer의 느슨한 연결을 가능케 하는 것이다. JButton이 선택되면, ButtonNotification이라 불리는 가상 서브클래스의 특정 메소드를 호출하는 대신 누구나 구현할 수 있는 인터페이스로 통지가 추상화된다. JButton은 첨부된 Observer(리스너)가 어떤 클래스인지 전혀 개의치 않는데, 실제로 버튼은 구현 클래스가 수정되더라도 오로지 Observer가 리스너를 구현한다는 사실에만 관심을 가진다.

Observer 패턴 사용 시 주의할 필요가 있는 여러 가지 복잡한 문제들이 있다. 첫째는 메모리 누출의 가능성이다. Observer에 대한 레퍼런스는 Subject에 의해 관리되는데, Subject가 레퍼런스를 해제할 때까지는 garbage collector로 Observer를 제거할 수 없다. 이런 가능성에 유의하여 적절한 상황에서 Observer를 제거해야 한다. 아울러 (적어도 이벤트 리스너를 등록할 때는) 일련의 Observer 객체가 unordered collection에서 관리된다는 점에 주목할 것. 먼저 등록된 리스너가 먼저 통지되는지 마지막에 통지되는지를 반드시 알아야 할 필요는 없으나 반드시 객체 A가 먼저 통지되고 이어서 객체 B가 통지되는 cascading 방식의 통지가 필요한 경우에는 중간 객체를 도입하여 순서가 지켜지도록 해야한다. 단지 Observer를 특정 순서로 등록한다고 해서 반드시 그 순서에 따라 통지가 이루어지는 것은 아니다.

Observer 패턴을 모델링하는 자바 플랫폼의 또 다른 영역으로는, guaranteed delivery, non-local distribution, persistence 등의 이점을 갖춘 JMS(Java Message Service)를 들 수 있다. JMS publish-subscribe 메시징 모델은 무한한 수의 가입자가 관심 있는 주제를 청취할 수 있게 해주는데, publish된 주제에 대한 메시지가 생성되면 모든 가입자들에게 내용이 통지된다.

그 밖에도 자바 플랫폼에는 Observer 패턴을 모델링하는 여러 다른 분야가 있으며, 이 패턴은 자바 플랫폼 전반에 걸쳐 자주 사용된다.

1995년설계 패턴(Design Patterns)이 출간된 이래로 이 패턴들에 대해 다양한 관점을 제시하고 추가 패턴을 소개하는 다른 책들이 발표된 바 있다. 그 중 다음 두 가지가 인기를 끌었다. 또한, 보다 심도 있는 설계 패턴에 관심이 있는 독자를 위해 기업 애플리케이션 아키텍처의 패턴(Patterns of Enterprise Application Architecture) 같은 책들도 나와 있다.

설계 패턴 일반에 관한 자세한 내용을 보려면 Wikipedia 엔트리(영문)을 참조하기 바란다.


맨 위로

본 메일은 수신을 동의한 회원님에게만 발송됩니다.
본 메일의 수신을 거부하거나 수신주소를 변경하려면 SKDN@Sun.com으로 문의 주시기 바랍니다.

SKDN(Sun Korea Developers Network)에서 J2EE/J2SE 테크팁 등 다양한 아티클들을 참고하세요.

Copyright 2003-2006 Sun Korea, Ltd. All rights reserved.


Posted by tornado
|
  Core Java Technologies Tech Tip에 오신 여러분을 환영합니다
Core Java Technologies
TECHNICAL TIPS
2006년 4월 21일자
  이번 호에서는,

» 애플릿 콘텍스트 스트림으로 작업하기
» Singleton 패턴에 대한 재고찰

에 대해 다룹니다.

이 문서는 Java 2 Platform, Standard Edition Development Kit 5.0 (JDK 5.0)을 기반으로 개발되었습니다. PDF 파일받기   

애플릿 콘텍스트 스트림으로 작업하기
 

요즘 애플릿에 대한 논의가 많지는 않으나 J2SE 1.4에서는 java.applet 패키지의 AppletContext 클래스에 세 가지 메소드가 추가되었다. 많은 사람들이 추가된 사실을 알아채지 못할 수도 있지만, 이 메소드들은 유용한 기능을 제공한다. 즉, 데이터를 스트림에 저장하고 각 스트림을 지정된 키(named key)에 매핑하는 것이다.

정보 저장을 위한 메인 메소드는 setStream()이다.
public void setStream(String name, InputStream stream) 스트림은 저장 시 키값 (Map과 유사한) 구조의 키에 연결되고, 매핑은 애플릿의 코드베이스에 한정된다. 이 말은 하나의 호스트에서 나온 애플릿이 다른 호스트의 스트림에 액세스하지 못한다는 것을 의미한다.

스트림이 저장된 후에는 싱글 스트림 또는 스트림 전체를 이용하여 이를 검색할 수 있다. 싱글 스트림을 얻으려면 getStream() 메소드를 이용하여 이름별로 요청을 한다.
public InputStream getStream(String name) getStreamKeys() 메소드를 이용하여 모든 스트림을 검색하는데, 이 작업을 수행할 때는 Map으로 돌아가지 않는다. 대신, 다음과 같은 String 이름의 Iterator를 얻는다.
public Iterator getStreamKeys() 사용자가 원하는 특정 스트림의 키 이름을 얻은 후에는 getStream() 메소드를 이용하여 해당 스트림을 얻는다. 이 때, 일반적으로 사용되는 패턴은 다음과 같다.
Iterator iter = getAppletContext().getStreamKeys(); if (iter != null) { while (iter.hasNext()) { String name = iter.next(); InputStream stream = getAppletContext().getStream(name); // read stream... } } 이들이 인풋 스트림이라는 점을 유념할 것. 문자로 작업하고자 하는 경우에는 반드시 문자 세트를 이용해야 한다. 예를 들어 String 오브젝트를 저장하려면 바이트를 얻어 AppletContext 내의 ByteArrayInputStream에 저장한다.
String message = ...; ByteArrayInputStream bais = new ByteArrayInputStream(message.getBytes("UTF-8")); getAppletContext().setStream("key-name", bais); 이 오브젝트를 읽으려면 스트림을 얻어 이를 InputStreamReader로 변환할 때 동일 문자 세트를 전달한다. Reader 오브젝트를 얻은 후에는 다음 예제처럼 문자를 읽을 수 있다.
InputStream stream = getAppletContext().getStream("key-name"); InputStreamReader isr = new InputStreamReader(stream, "UTF-8"); BufferedReader reader = new BufferedReader(isr); String line = reader.readLine(); API는 사실상 이것이 전부라 할 수 있다. 'setStream() 메소드를 이용하여 새로운 스트림을 저장하고, getStream()을 이용하여 스트림을 되돌린다. getStreamKeys()를 이용하여 스트림 키 세트를 얻는다. ' 이것이 스트림에 관해 알아 두어야 할 전부인 것처럼 보일지 모르지만, 그렇다면 스트림 컨텐츠를 제거하려면 어떻게 해야 할까? 그 답은 다음과 같다. 특정 키와 연결된 InputStream으로 null을 전달한다. 이렇게 하면 스트림의 컨텐츠가 시스템에서 제거된다.
getAppletContext().setStream("key-name", null); 이번에는 API의 데모를 살펴보기로 하자. 먼저, 프로그램 로더인 HTML 파일을 생성해야 한다. 200x200의 디스플레이 면적을 필요로 하는 StreamsApplet으로 명명된 애플릿의 경우, HTML 파일에는 다음과 같은 애플릿 태그가 포함되어야 한다.
<applet code=StreamsApplet width=200 height=200> </applet> StreamsApplet 애플릿은 키값 쌍을 위해 2개의 텍스트 필드를 제공하는데, 이 때 키는 lookup name이며 값은 저장될 InputStream 컨텐츠이다. 아울러 애플릿은 2개의 버튼을 디스플레이한다. 첫 번째 버튼은 명명된 스트림을 추가하고(또는 기존의 것을 업데이트한다), 두 번째 버튼은 명명된 스트림을 제거한다. 애플릿은 JList에 현재의 이름 세트를 표시한다.

Streams Demo


다음은 사용자 인터페이스 생성에 사용되는 코드이다.
import javax.swing.*; import javax.swing.event.*; import java.awt.*; import java.awt.event.*; import java.io.*; import java.util.*; public class StreamsApplet extends JApplet { private static final String CHARSET = "UTF-8"; JButton add; JButton remove; JList list; JTextField key; JTextField value; public void init() { JLabel keyLabel = new JLabel("Key"); keyLabel.setDisplayedMnemonic('K'); key = new JTextField(); keyLabel.setLabelFor(key); JLabel valueLabel = new JLabel("Value"); valueLabel.setDisplayedMnemonic('V'); value = new JTextField(); valueLabel.setLabelFor(value); JPanel topPanel = new JPanel(new GridLayout(2,2)); topPanel.add(keyLabel); topPanel.add(key); topPanel.add(valueLabel); topPanel.add(value); add(topPanel, BorderLayout.NORTH); list = new JList(); list.setSelectionMode (ListSelectionModel.SINGLE_SELECTION); JScrollPane pane = new JScrollPane(list); add(pane, BorderLayout.CENTER); add = new JButton("Add/Update"); add.setDisplayedMnemonic('A'); remove = new JButton("Remove"); remove.setDisplayedMnemonic('R'); JPanel bottomPanel = new JPanel(); bottomPanel.add(add); bottomPanel.add(remove); add(bottomPanel, BorderLayout.SOUTH); } } 이제 스트림 추가와 업데이트를 위한 액션을 추가해 보자. Add/Update 버튼 뒤의 ActionListener는 각각의 텍스트 필드에서 이름과 스트림 컨텐츠를 획득한 다음 이를 AppletContext에 저장해야 한다. 스트림을 추가한 후에는 JList에 스트림 목록이 표시되고 ActionListener가 텍스트 필드를 소거해야 한다.
String keyText = key.getText(); String valueText = value.getText(); try { ByteArrayInputStream bais = new ByteArrayInputStream(valueText.getBytes(CHARSET)); getAppletContext().setStream(keyText, bais); } catch (IOException ioe) { JOptionPane.showMessageDialog(StreamsApplet.this, "Unable to save", "Error", JOptionPane.ERROR_MESSAGE); } updateList(); key.setText(""); value.setText(""); updateList() 메소드는 상당히 간단한데, 단순히 이름 목록을 얻어 이를 JList에 넣기만 하면 된다.

DefaultListModel model = new DefaultListModel(); Iterator<String> iter = getAppletContext().getStreamKeys(); if (iter != null) { while (iter.hasNext()) { model.addElement(iter.next()); } } list.setModel(model); Remove 버튼 뒤의 ActionListener는 키 텍스트 필드의 모든 이름에 대해 단순히 스트림을 null로 설정한다. 이 경우에도 제거 후에 이름 목록을 업데이트하고 텍스트 필드를 소거해야 한다.

String keyText = key.getText(); try { getAppletContext().setStream(keyText, null); } catch (IOException ioe) { JOptionPane.showMessageDialog(StreamsApplet.this, "Unable to clear", "Error", JOptionPane.ERROR_MESSAGE); } updateList(); key.setText(""); value.setText(""); 이것으로 작업이 모두 완료된 것은 아니다. 목록에서 이름을 선택하면 현재의 값이 표시되는데, 이 작업은 ListSelectionListener를 통해 이루어진다. 리스너는 JList에서 선택된 값을 획득한 다음 애플릿 컨텍스트에서 스트림을 룩업한다. 이름을 찾을 수 없으면 getStream() 메소드는 null을 리턴한다. 단, JList에는 스트림과 일치하는 이름만 포함되므로 확인 작업이 필요하지는 않다.
String selection = (String)list.getSelectedValue(); try { InputStream stream = getAppletContext().getStream(selection); InputStreamReader isr = new InputStreamReader(stream, CHARSET); BufferedReader reader = new BufferedReader(isr); String line = reader.readLine(); key.setText(selection); value.setText(line); } catch (IOException ioe) { JOptionPane.showMessageDialog(StreamsApplet.this, "Unable to read", "Error", JOptionPane.ERROR_MESSAGE); } 이것을 모두 합치면 애플릿 컨텍스트에 명명된 스트림을 저장할 완벽한 애플릿이 구현된다. 다음은 모든 리스너를 각각의 해당 컴포넌트에 첨부하기 위한 소스의 전체 내용이다.
import javax.swing.*; import javax.swing.event.*; import java.awt.*; import java.awt.event.*; import java.io.*; import java.util.*; public class StreamsApplet extends JApplet { private static final String CHARSET = "UTF-8"; JButton add; JButton remove; JList list; JTextField key; JTextField value; public void init() { JLabel keyLabel = new JLabel("Key"); keyLabel.setDisplayedMnemonic('K'); key = new JTextField(); keyLabel.setLabelFor(key); JLabel valueLabel = new JLabel("Value"); valueLabel.setDisplayedMnemonic('V'); value = new JTextField(); valueLabel.setLabelFor(value); JPanel topPanel = new JPanel(new GridLayout(2,2)); topPanel.add(keyLabel); topPanel.add(key); topPanel.add(valueLabel); topPanel.add(value); add(topPanel, BorderLayout.NORTH); list = new JList(); list.setSelectionMode( ListSelectionModel.SINGLE_SELECTION); JScrollPane pane = new JScrollPane(list); add(pane, BorderLayout.CENTER); add = new JButton("Add/Update"); add.setMnemonic('A'); remove = new JButton("Remove"); remove.setMnemonic('R'); JPanel bottomPanel = new JPanel(); bottomPanel.add(add); bottomPanel.add(remove); add(bottomPanel, BorderLayout.SOUTH); ActionListener addListener = new ActionListener() { public void actionPerformed(ActionEvent e) { String keyText = key.getText(); String valueText = value.getText(); try { ByteArrayInputStream bais = new ByteArrayInputStream( valueText.getBytes(CHARSET)); getAppletContext().setStream(keyText, bais); } catch (IOException ioe) { JOptionPane.showMessageDialog(StreamsApplet.this, "Unable to save", "Error", JOptionPane.ERROR_MESSAGE); } updateList(); key.setText(""); value.setText(""); } }; add.addActionListener(addListener); ActionListener removeListener = new ActionListener() { public void actionPerformed(ActionEvent e) { String keyText = key.getText(); try { getAppletContext().setStream(keyText, null); } catch (IOException ioe) { JOptionPane.showMessageDialog(StreamsApplet.this, "Unable to clear", "Error", JOptionPane.ERROR_MESSAGE); } updateList(); key.setText(""); value.setText(""); } }; remove.addActionListener(removeListener); ListSelectionListener selectListener = new ListSelectionListener() { public void valueChanged(ListSelectionEvent e) { String selection = (String)list.getSelectedValue(); try { InputStream stream = getAppletContext().getStream(selection); InputStreamReader isr = new InputStreamReader(stream, CHARSET); BufferedReader reader = new BufferedReader(isr); String line = reader.readLine(); key.setText(selection); value.setText(line); } catch (IOException ioe) { JOptionPane.showMessageDialog(StreamsApplet.this, "Unable to read", "Error", JOptionPane.ERROR_MESSAGE); } } }; list.addListSelectionListener(selectListener); updateList(); } private void updateList() { DefaultListModel model = new DefaultListModel(); Iterator<String> iter = getAppletContext().getStreamKeys(); if (iter != null) { while (iter.hasNext()) { model.addElement(iter.next()); } } list.setModel(model); } } Java 플러그인 기술 덕분에, 대부분의 데스크톱에서도 애플릿을 브라우저에서 실행할 수 있게 되었다. 최신 자바 소프트웨어를 확인하고 새로운 애플릿을 시험해보고 싶다면 java.com을 방문하기 바란다.

맨위로

Singleton 패턴에 대한 재고찰
 

2006년 2월 8일자 테크 팁 Singleton 패턴에 대해 많은 피드백이 접수되었다. 이 피드백 중에는 Singleton 클래스가 단일 클래스 로더를 통해 공유되지 않으면 Singleton이 아니라는 사실을 강조하는 내용도 포함되어 있다.

사실인즉, 서로 다른 클래스 로더에서 로드된 클래스들은 이름이 같고 동일한 패키지에 속하더라도 동일한 클래스가 아니다.

이를 이해하는 것이 중요한 이유는 무엇일까? 일부 환경에서는 흔히 복수 클래스 로더를 사용하고 있기 때문이다. 예를 들어, Java 2 Platform, Enterprise Edition (J2EE) 애플리케이션 서버는 클래스가 더 이상 필요치 않게 되면 클래스를 언로드할 수 있도록 복수의 클래스 로더를 사용한다(클래스에 대한 클래스 로더를 제거하면 메모리에서 클래스가 제거된다). 이 외에도, J2EE 애플리케이션 서버는 보안상의 이유로 클래스 격리를 위해 복수의 클래스 로더를 사용하기도 한다.

따라서, Singleton 클래스가 단일 클래스 로더(가령 시스템 클래스 로더)를 통해 공유되지 않는다면 그것은 Singleton이라고 할 수 없다.

맨위로

본 메일은 수신을 동의한 회원님에게만 발송됩니다.
본 메일의 수신을 거부하거나 수신주소를 변경하려면 SKDN@Sun.com으로 문의 주시기 바랍니다.

SKDN(Sun Korea Developers Network)에서 J2EE/J2SE 테크팁 등 다양한 아티클들을 참고하세요.

Copyright 2003-2006 Sun Korea, Ltd. All rights reserved.


Posted by tornado
|
  Enterprise Java Technologies Tech Tip에 오신 여러분을 환영합니다
Enterprise Java Technologies
테크팁
2006년 5월 4일자
  이번 호에서는,

» EJB 3.0을 이용하여 웹 서비스 개발하기
» 커스텀 빈을 이용하여 GlassFish 관리 시스템 확장하기

에 대해 다룹니다.

이 팁들은 Java EE 5의 오픈소스 구현(GlassFish)을 이용하여 개발되었으며, GlassFish 프로젝트 페이지에서 GlassFish를 다운로드 받으실 수 있습니다.

-샘플 아카이브 다운로드 받기-
EJB 3.0을 이용하여 웹 서비스 개발하기
커스텀 빈을 이용하여 GlassFish 관리 시스템 확장하기

EJB 3.0을 이용하여 웹 서비스 개발하기
 

Java EE, JSR 109를 위한 웹 서비스 명세에서는 웹 서비스를 구현하는 두 가지 방법을 정의한다. 그 중 한 가지 방법은 자바 클래스 프로그래밍 모델에 기초한 것으로, 웹 서비스가 웹 컨테이너에서 실행되는 자바 클래스에 의해 구현된다. 또 다른 방법은 EJB(Enterprise JavaBeans) 프로그래밍 모델에 기초한 것으로, 웹 서비스가 EJB 컨테이너에서 실행되는 stateless 세션 빈으로 구현된다. 이전의 테크 팁 JAX-WS를 이용한 웹 서비스 개발에서는 자바 클래스 프로그래밍 모델과 JAX-WS(Java API for XML Web Services) 2.0, JSR 224를 이용하여 웹 서비스를 개발하는 방법에 대해 알아보았다. 이번 팁에서는 JAX-WS와 EJB 프로그래밍 모델을 이용하여 웹 서비스를 개발하는 방법을 배우게 될 것인데, 특히 EJB 3.0 stateless 세션 빈을 이용하여 Calculator 서비스(이전 테크 팁에서 다룬 것과 동일한 Calculator 서비스)를 구현하는 방법에 대해 자세히 살펴보도록 하자.

본 팁에는 예제 패키지가 포함되어 있고, 이 예제에는 EJB 3.0 기반의 Calculator 서비스에 액세스하는 독립형 자바 클라이언트가 설명되어 있다. 또한 여기에는 GlassFish라고 불리는 Java EE 5의 오픈 소스 레퍼런스 구현이 사용되었다. GlassFish는 GlassFish 커뮤니티 다운로드 페이지에서 다운로드할 수 있다.

EJB 3.0 Stateless 세션 빈 클래스 작성하기

우선 서비스를 위한 stateless 세션 빈을 작성하는 것부터 시작해보자. Java EE 5 플랫폼에서 크게 개선된 내용 중 하나로 대폭 단순해진 EJB 프로그래밍 모델을 들 수 있는데, 이는 Enterprise JavaBeans 3.0 Specification, JSR-220에 정의되어 있다. 단순화된 기능 중 한 가지를 예로 들면, 빈 구현 클래스가 더 이상 javax.ejb.SessionBean 또는 javax.ejb.EntityBean 인터페이스를 구현하도록 요구하지 않는다는 것이다. 단순히 클래스에 주석을 달기만 하면 클래스를 세션 빈이나 엔티티 빈으로 선언할 수 있는데, 실례로 클래스에 @Stateless 주석을 달면 클래스를 stateless 세션 빈으로 선언할 수 있다.

EJB 3.0은 다음과 같이 빈 구현 클래스를 위한 추가 규칙을 명시한다.

  • 클래스는 반드시 public으로 선언되어야 하며 어떤 인자도 받지 않는 기본값 생성자(constructor)를 가져야 한다.

  • 클래스는 절대로 final 또는 abstract여서는 안 되며 반드시 톱 레벨 클래스여야 한다.

  • 클래스는 finalize() 메소드를 정의해서는 안 된다.

EJB 3.0에서 단순화된 또 한 가지 내용은 세션 빈을 위한 컴포넌트 인터페이스 또는 홈 인터페이스가 더 이상 요구되지 않는다는 점이다. 세션 빈이 필요로 하는 한 가지 인터페이스는 빈의 비즈니스 메소드를 정의하는 비즈니스 인터페이스이다. 비즈니스 인터페이스의 비즈니스 메소드는 컴포넌트 인터페이스의 비즈니스 메소드와 달리 java.remote.RemoteException을 throw할 필요가 없지만 비즈니스 메소드는 임의의 애플리케이션 예외와 관련하여 throws 절을 정의할 수 있다. 또한 EJB 3.0 비즈니스 메소드는 staticfinal이 될 수 없다.

이러한 단순화와 규칙을 전제로 하여, EJB 3.0 프로그래밍 모델을 따르는 Calculator 클래스의 stateless 세션 빈에 대해 알아보자(Calculator 클래스의 소스 코드는 설치된 예제 패키지의 엔드포인트 디렉토리에 들어 있음).

package endpoint; import javax.ejb.Stateless; @Stateless public class Calculator { public Calculator() {} public int add(int i, int j) { int k = i +j ; System.out.println(i + "+" + j +" = " + k); return k; } }

EJB 3.0 빈은 javax.ejb.SessionBean 인터페이스를 구현할 필요가 없기 때문에 더 이상 ejbActivateejbPassivate와 같은 비구현 라이프사이클 메소드를 포함시킬 필요가 없다. 따라서 훨씬 단순하고 완벽한 클래스가 생성된다. EJB 3.0에 정의된 다양한 주석들은 컴포넌트를 위한 배치 기술자 작성의 필요성을 줄이거나 없애줌으로써 개발자 및 배치자의 부담을 상당히 덜어준다.

EJB 3.0 빈을 웹 서비스로 표시하기

빈을 웹 서비스로 만들려면 간단히 클래스에 @WebService 주석을 달면 된다. 이것은 javax.jws.WebService 패키지에 정의된 주석 타입으로, Java Platform, JSR 181을 위한 웹 서비스 메타데이터에 지정되어 있다. 다음은 웹 서비스로 표시된 Calculator 클래스 코드이다.

package endpoint; import javax.ejb.Stateless; import javax.jws.WebService; @Stateless @WebService public class Calculator { public Calculator() {} public int add(int i, int j) { int k = i +j ; System.out.println(i + "+" + j +" = " + k); return k; } }

자바 클래스를 @WebService 주석으로 표시하면 서비스 구현 클래스가 된다. 단, 서비스 엔드포인트 인터페이스를 구현할 필요가 없다는 점에 유의할 것. JSR 109에 따르면, javax.jws.WebService 주석이 첨부된 서비스 구현 빈을 제공하기만 하면 된다. 그런 다음 배치 툴을 이용해서 자바 WSDL 매핑을 위한 JAX-WS 규칙을 적용함으로써 서비스 엔드포인트 인터페이스는 물론, WSDL 문서까지 생성할 수 있다.

웹 서비스 패키지하기

EJB 프로그래밍 모델에 기초한 웹 서비스는 JAR 파일로 패키지되어야 하는데, 즉 @WebService 주석을 이용하여 서비스 구현 빈 클래스(독립 클래스가 있을 경우에는 이와 함께)와 서비스 엔드포인트 인터페이스 클래스(명시적으로 제공될 경우)를 패키지하기만 하면 된다. 이 외에도, @Stateless 주석은 ejb-jar.xml을 패키지해야 하는 수고를 덜어주기도 한다. 이와 대조적으로, EJB 2.0이나 이전 버전에 기초한 웹 서비스를 JAX-RPC 방식으로 패키지하는 경우에는 사용자가 서비스 엔드포인트 인터페이스 클래스, 서비스 구현 빈 클래스(및 독립 클래스), 생성된 portable artifacts, JAX-RPC 매핑 파일, 웹 서비스 배치 기술자(webservices.xmlejb-jar.xml) 등을 제공해야만 했다.

JSR 224, JSR 109, JSR 181 및 JSR 220의 경우, 애플리케이션 서버 배치 툴을 이용하여 웹 서비스 배치를 위한 배치 기술자(사용자가 명시적으로 제공하지 않은 경우)를 비롯하여 필요한 모든 artifacts를 생성할 수 있다. EJB JAR 파일에 번들로 포함된 이 artifacts는 EJB 컨테이너에 배치된다. 배치자는 전술한 artifacts를 명시적으로 제공하고 배치 시 이를 EJB 모듈에 패키지함으로써 @WebService@Stateless 주석에 의해 지정된 값들을 오버라이트할 수 있다. 본 팁의 경우에는 다음 파일들이 배치될 EJB 모듈에 패키지되어 있다.

endpoint/Calculator.class endpoint/jaxws/Add.class endpoint/jaxws/AddResponse.class

나머지 배치 artifacts는 애플리케이션 서버(이 경우 GlassFish)에 의해 생성된다.

클라이언트 작성하기

웹 서비스를 배치한 후에는 클라이언트 프로그램으로 액세스가 가능한데, 클라이언트는 @WebServiceRef 주석을 이용하여 EJB 3.0 기반의 웹 서비스에 레퍼런스를 선언한다. @WebServiceRef 주석은 javax.xml.ws 패키지에 포함되어 있으며, Java Platform, JSR 181을 위한 JAX-WS 2.0 웹 서비스 메타데이터에 지정되어 있다. 본 팁에 사용된 클라이언트 프로그램 JAXWSClient의 소스 코드를 살펴보면(JAXWSClient의 소스 코드는 설치된 예제 패키지의 client 디렉토리에 들어 있음), 다음과 같은 내용을 확인할 수 있다.

@WebServiceRef(wsdlLocation= "http://localhost:8080/CalculatorService/Calculator?WSDL") static endpoint.CalculatorService service;

@WebServiceRef 내의 wsdlLocation 파라미터의 값은 일종의 URL로, 레퍼런스된 서비스의 WSDL 파일의 위치를 나타낸다. (@WebServiceRef 주석은 옵션으로 제공되는 추가 속성을 지원하며, 이 옵션 속성은 JAX-WS 2.0 스펙의 섹션 7.9에 지정되어 있다.) service로 명명된 정적 변수는 애플리케이션 클라이언트 컨테이너에 의해 인젝트된다.

JAXWSClient의 소스 코드를 좀더 살펴보면 다음과 같은 내용을 확인할 수 있다.

endpoint.Calculator port = service.getCalculatorPort();

service 오브젝트는 웹 서비스의 Calculator 포트에 액세스하기 위한 getCalculatorPort 메소드를 제공한다. 단, endpoint.CalculatorServiceendpoint.Calculator 모두 wsimport 유틸리티를 이용하여 생성되는 portable artifacts라는 점에 유의할 것. wsimport 유틸리티는 JAX-WS artifacts 생성에 사용되는데, 예제 프로그램 실행 시 클라이언트 구축을 위해 호출된다.

포트를 획득한 후에는 오브젝트 상에서 자바 메소드를 호출하는 것처럼 포트 상에서 비즈니스 메소드를 호출할 수 있다. 예를 들어, JAXWSClient의 다음 행은 Calculator의 add 메소드를 호출한다.

int ret = port.add(i, 10);

예제 코드 실행하기

본 테크팁에는 예제 패키지가 포함되어 있으며, 예제 패키지에서는 테크팁에서 다룬 기법을 예시한다. 예제를 설치하고 실행하려면 다음의 작업 절차를 따르도록 한다.

  1. GlassFish를 아직 구하지 못했다면 GlassFish 커뮤니티 다운로드 페이지에서 다운로드한다.

  2. 그런 다음 아래의 환경 변수를 설정한다.

    GLASSFISH_HOME: GlassFish의 설치 장소(가령 C:\Sun\AppServer)을 표시해야 한다.

    ANT_HOME: ant의 설치 장소를 표시해야 한다. ant는 다운로드한 GlassFish 번들에 포함되어 있다. (Windows에서는 lib\ant 서브디렉토리에 위치함)

    JAVA_HOME: 사용자 시스템에서의 JDK 5.0 위치를 표시해야 한다.

    아울러, ant 위치를 각자의 PATH 환경 변수에 추가한다.

  3. 해당 테크팁의 예제 패키지를 다운로드하여 압축을 푼다. 이 때, 새로 압축이 풀린 디렉토리는 <sample_install_dir>/ttmar2006ejb-ws로 표시되어야 하는데, 여기서 <sample_install_dir>은 예제 패키지가 설치된 디렉토리이다. 예를 들어, Windows의 C:\에 압축을 해제했다면 새로 생성된 디렉토리는 C:\ttmar2006ejb-ws가 되어야 한다. ttmar2006ejb-ws 아래의 ejb-techtip 디렉토리에는 예제를 위한 소스 파일과 기타 지원 파일이 포함되어 있다.

  4. ejb-techtip 디렉토리로 이동하여 build.properties 파일을 적절히 편집해야 하는데, 예를 들어 admin 호스트가 원격인 경우에는 admin.host의 기본값(localhost)을 해당 원격 호스트로 변경하면 된다.

  5. 다음 명령어를 입력하여 GlassFish를 시작한다.

    <GF_install_dir>/bin/asadmin start-domain domain1

    이 때, <GF_install_dir>은 GlassFish가 설치된 디렉토리를 나타낸다.

  6. ejb-techtip 디렉토리에서 다음 명령어를 실행한다.

    ant build

    빌드 디렉토리가 생성되고 클래스가 컴파일된 다음, 컴파일된 클래스가 빌드 디렉토리로 들어간다. 또한 아카이브 디렉토리와 JAR 파일이 생성되고, JAR 파일이 아카이브 디렉토리로 들어간다.

    ant deploy

    이 명령어는 JAR 파일을 GlassFish 상에 배치한다.

    ant build-client

    이 명령어는 portable artifacts를 생성하고 클라이언트 소스 코드를 컴파일한다.

    ant run

    이 명령어는 애플리케이션 클라이언트를 실행하고 Calculator 서비스에서 add 연산을 10회 호출하여 0에서 9까지의 숫자에 10을 추가한다. 이 때, 다음과 같은 내용이 표시되어야 한다.

    실행:

    [echo] Executing appclient with client class as client.JAXWSClient [exec] Retrieving port from the service endpoint.CalculatorService@159780d [exec] Invoking add operation on the calculator port [exec] Adding : 0 + 10 = 10 [exec] Adding : 1 + 10 = 11 [exec] Adding : 2 + 10 = 12 [exec] Adding : 3 + 10 = 13 [exec] Adding : 4 + 10 = 14 [exec] Adding : 5 + 10 = 15 [exec] Adding : 6 + 10 = 16 [exec] Adding : 7 + 10 = 17 [exec] Adding : 8 + 10 = 18 [exec] Adding : 9 + 10 = 19
  7. GlassFish에서 EJB 모듈을 배치 해제하려면 다음 명령어를 실행한다.

    ant undeploy

저자 소개

Manisha Umbarje는 Sun Java System Application Server의 제품 엔지니어링 그룹 소속임.

맨위로

커스텀 빈을 이용하여 GlassFish 관리 시스템 확장하기
 

J2SE(Java 2 Platform, Standard Edition) 5.0에서 크게 개선된 부분으로 모니터링과 관리 기능을 들 수 있으며, J2SE 5.0에 도입된 주요 특징에는 instrumented JVM(Java Virtual Machine)과 JVM을 모니터하고 감시하기 위한 java.lang.management API가 포함된다. 또한 API는 메모리 이용률, 스레드 상태, 클래스 로딩 활동, 가비지 컬렉션 전략 등을 비롯하여 다양한 JVM 관련 정보에 대한 로컬 및 원격 액세스를 가능하게 해준다. 이와 같이 강화된 통합 관리 및 모니터링 지원 기능은 J2SE 5.0 기반의 어떠한 관리 애플리케이션에서도 이용이 가능하다.

GlassFish와 MBeans

이런 기능을 활용하는 툴 중 하나가 바로 Java EE 5의 오픈 소스 애플리케이션 서버 구현인 GlassFish인데, GlassFish 애플리케이션 서버는 자체의 관리 인프라 내에서 J2SE 5.0 기반의 강화된 모니터링 및 관리 기능을 모두 활용한다. 또한 여기에는 플랫폼 MBean 서버를 이용하여 애플리케이션 서버 MBeans를 등록하는 기능도 포함되어 있다. Management Beans(일명 "MBeans")는 JMX(Java Management Extensions) 스펙에 준한 디자인 패턴을 따르는 자바 오브젝트로, 리소스를 공급하는 데 이용된다. 본 팁은 사용자가 JMX에 대한 기본 지식을 이미 가지고 있는 것으로 가정한다. JMX에 관한 개요를 보려면 테크팁 JMX 기술 이해하기를 참조할 것.

J2SE 5.0에 함께 도입된 플랫폼 MBean 서버는 JVM에 내장된 JMX 기반 에이전트로, 관리 애플리케이션이 MBeans에 액세스할 수 있게 해준다. 이 에이전트는 JVM에서 실행되는 모든 매니지드 컴포넌트에 의해 공유될 수 있다. GlassFish는 플랫폼 MBean 서버를 통해 시스템과 애플리케이션별로 MBeans에 대한 종합적이고 통합된 모니터링 및 관리 뷰를 제공할 수 있으며, J2SE 5.0 이전에 요구되었던 것처럼 자체 에이전트의 인스턴스를 생성하는 대신 이 내장 에이전트를 이용할 수 있다. 애플리케이션 서버 MBeans는 플랫폼 MBean 서버 리포지토리에 등록되기 때문에, 자바 모니터링 및 관리 콘솔(JConsole)과 같은 툴은 애플리케이션 서버 MBeans에 의해 제공되는 모든 리소스에 관한 정보를 디스플레이할 수 있다.

GlassFish와 커스텀 MBeans

사용자는 자체 커스텀 MBeans를 생성하여 등록함으로써 GlassFish의 관리 기능을 확장할 수 있다. 커스텀 MBeans는 모니터링 및 관리 기능의 동적 인젝션을 가능케 해줄 뿐 아니라 instrumented 커스텀 MBean 속성을 지속시켜 줌으로써 애플리케이션 서버를 재시작해야 할 경우에라도 활성 상태를 그대로 유지할 수 있게 한다. 커스텀 MBeans의 유용성을 엿볼 수 있는 한 가지 예가 바로 GlassFish의 자체 관리 프레임워크인데, 이는 규칙 기반의 이벤트 관리 시스템으로, 사용자는 커스텀 MBeans로 구현되는 커스텀 액션을 시스템 관리 규칙에 추가할 수 있다.

예제: 모니터링 및 관리 기능 확장하기

본 팁에서는 커스텀 MBeans를 이용하여 GlassFish의 모니터링 및 관리 기능을 확장하는 예제를 제시하고, 이 예제를 통해 웹 서비스로부터 정기적으로 획득하는 데이터를 처리하는 Java EE 애플리케이션을 확장해 보도록 한다. 또한 관리 확장을 위해 모니터 대상 이벤트, 그리고 그 이벤트에 대한 응답으로 애플리케이션이 취할 액션을 추가하도록 한다.

이벤트는 이메일 주소 목록을 업데이트하는 것이고, 액션은 업데이트된 이메일 주소 목록으로 이메일을 전송하는 것이다. 이 시나리오에서, 웹 서비스의 클라이언트이기도 한 커스텀 MBean은 웹 서비스를 폴링한 후에 이메일 주소 목록을 업데이트한다. 하지만, 이 예제에서는 단순화를 위해서 이메일 주소의 문자열이 커스텀 MBean의 속성으로 되어 있다. 사용자는 JConsole을 이용하여 직접 목록을 수정하고, 속성이 수정되면 리스닝 커스텀 MBean에 통지가 이루어진다. 그런 다음 리스닝 커스텀 MBean이 업데이트된 이메일 주소 목록(즉, 업데이트된 속성의 값)에 이메일을 전송하여 이벤트를 처리한다.

본 테크팁에는 예제 아카이브가 포함되어 있으며, 여기에는 예제를 위한 소스 코드, 그리고 컴파일된 클래스를 비롯하여 예제에서 사용되는 클래스를 위한 javadoc이 함께 포함되어 있다.

1단계: 셋업

초기 설정 작업부터 시작해보자. GlassFish를 아직 구하지 못했다면 GlassFish 다운로드 페이지에서 다운로드한 다음 아래의 환경변수를 설정한다.

  • GLASSFISH_HOME. GlassFish의 설치 장소(가령 C:\Sun\AppServer)을 표시해야 한다.

  • JAVA_HOME. 사용자 시스템에서의 JDK 5.0 위치를 표시해야 한다.

2단계: GlassFish 시작하기

다음 명령어를 입력하여 GlassFish를 시작한다.

<GF_install_dir>/bin/asadmin start-domain domain1

이 때, <GF_install_dir>은 GlassFish가 설치된 디렉토리를 나타낸다.

3단계: 예제 아키이브 다운로드하기

해당 팁의 예제 아카이브를 다운로드하여 압축을 푼다.

jar xvf ttmar2006custmbean.jar

압축을 풀고 나면 META-INF, techtip 및 javadoc 디렉토리가 표시되어야 한다. techtip 디렉토리에는 예제용 소스 코드, 그리고 컴파일된 클래스가 포함되어 있다.

4단계: 커스텀 MBeans 생성하기

본 예제에서는 2개의 커스텀 MBeans--이벤트 소스용과 이벤트 청취용(이벤트 "싱크")--를 사용한다. 이 2개의 MBeans를 위한 소스 코드는 techtip/src 디렉토리에 들어 있다.

커스텀 MBean은 MBean 인터페이스와 MBean 구현 클래스를 필요로 하는데, 이벤트 소스용 커스텀 MBean 인터페이스는 EventSourceCustomMBean이며, 그 구현 클래스는 EventSourceCustom이다. 그리고 이벤트 싱크를 위한 커스텀 MBean 인터페이스는 EventSinkCustomMBean이며, 그 구현 클래스는 EventSinkCustom이다.

커스텀 MBeans를 위한 소스 파일을 생성한 후에는 파일들을 com.example.mbeans 패키지 구조에 컴파일할 수 있다(이는 옵션사항이며, 컴파일된 클래스는 예제 아카이브에 포함되어 있음). 파일을 컴파일하려면 다음을 입력한다.

javac -d . EventSourceCustom.java EventSourceCustomMBean.java javac -d . EventSinkCustom.java EventSinkCustomMBean.java

EventSinkCustom 클래스를 컴파일할 때는 각 사용자의 클래스패스에 mail.jaractivation.jar 파일이 들어 있는지 확인해야 한다.

5단계: 커스텀 MBean 클래스 복사하기

com/example/mbeans 디렉토리와 그 내용을 MBean 클래스로더 디렉토리에 복사한다. MBean 클래스로더 디렉토리는 <domain>/applications/mbeans이고, 이 때 <domain>은 애플리케이션이 배치된 도메인을 나타낸다. 본 예제에서는 애플리케이션이 기본값 GlassFish 도메인인 domain1에 배치된 것으로 가정한다. 따라서 com/example/mbeans 디렉토리와 그 내용을 <GF_install_dir>/glassfish/domains/domain1/applications/mbeans에 복사한다. 그러면 /com/example/mbeans 디렉토리가 생성되고 커스텀 MBean 클래스와 인터페이스가 <GF_install_dir>/glassfish/domains/domain1/applications/mbeans에 복사된다.

6단계: 이벤트 소스 커스텀 MBean 배치하기

다음과 같이 이벤트 소스 커스텀 MBean, EventSourceCustom을 배치한다(명령어는 한 행에 입력해야 한다).

<GF_install_dir>/bin/asadmin create-mbean --user admin --passwordfile password.txt --port 4848 com.example.mbeans.EventSourceCustom

플랫폼 MBean 서버에 EventSourceCustom이 등록된다.

다음 명령어를 이용하여 커스텀 MBean이 배치되었는지 확인할 수 있다(명령어는 한 행에 입력해야 한다).

<GF_install_dir>/bin/asadmin list-mbeans --user admin --passwordfile password.txt

다음과 같은 내용이 표시되어야 한다.

com.example.mbeans.EventSourceCustom user:impl-class-name=com.example.mbeans.EventSourceCustom, name=com.example.mbeans.EventSourceCustom Enabled Command list-mbeans executed successfully.

7단계: 이벤트 싱크 커스텀 MBean 배치하기

다음과 같이 이벤트 싱크 커스텀 MBean, EventSinkCustom을 배치한다(명령어는 한 행에 입력해야 한다).

<GF_install_dir>/bin/asadmin create-mbean --user admin --passwordfile password.txt --port 4848 --objectname "user:impl-class-name=com.example.mbeans.EventSinkCustom, name= custom-event-sink" --attributesHostName=<yourmailserver>:Id=<yourId>: Password=<yourpw> com.example.mbeans.EventSinkCustom

단, 명령어의 HostName, Id, Password 등의 파라미터에 유의할 것. 메일 서버에 접속하려면 이 파라미터들이 지정되어야 한다. 파라미터는 커스텀 MBean의 속성이다. <yourmailserver>는 각자의 메일 서버 이름으로, <yourId>는 각자의 ID로, <yourpw>는 각자의 비밀번호로 대체한다.

앞에서 언급한 것처럼, instrumented 커스텀 MBean 속성을 지속시켜 줌으로써 애플리케이션 서버를 재시작해야 할 경우에라도 활성 상태를 그대로 유지할 수 있다. 따라서, 명령어의 파라미터를 지정하면 커스텀 MBean의 런타임 파라미터가 구성된다. 하지만 MBean이 생성된 후에는 서버가 재시작하더라도 파라미터는 기존의 상태를 지속하게 된다.

이번에도 다음 명령어를 이용하여 커스텀 MBean이 배치되었는지 확인할 수 있다(명령어는 한 행에 입력해야 한다).

<GF_install_dir>/bin/asadmin list-mbeans --user admin --passwordfile password.txt

다음과 같은 내용이 표시되어야 한다.

com.example.mbeans.EventSourceCustom user:impl-class-name=com.example.mbeans.EventSourceCustom, name=com.example.mbeans.EventSourceCustom Enabled com.example.mbeans.EventSinkCustom user:impl-class-name=com.example.mbeans.Event SinkCustom, name=custom-event-sink Enabled Command list-mbeans executed successfully.

8단계: 이메일 목록 업데이트하기

본 예제에서는 JConsole을 이용하여 이메일 주소의 문자열이 포함된 커스텀 MBean의 속성을 업데이트한다.

다음 명령어를 입력하여 JConsole을 시작한다.

<JAVA_HOME>/bin/jconsole

JConsole를 시작하면 Local/Remote/Advanced JMX 접속 탭이 있는 접속 대화상자가 표시되어야 한다. Remote 탭을 클릭하고 해당 호스트(localhost), 포트(GlassFish의 JMX 접속 서버는 포트 8686에서 청취), 사용자 이름(admin), 비밀번호(adminadmin) 등의 값을 입력한다.

Remote 탭의 디스플레이에서 Connect 버튼을 클릭하면 RMI 커넥터를 통해 플랫폼 MBean 서버로의 접속이 이루어진다. 이어지는 Connection 창에서 MBeans 탭을 클릭하고, 창의 왼쪽 구획에 위치한 MBean 트리에서 사용자 브랜치를 확장한다. com.example.mbeans.EventSourceCustom 아래에 서버 엔트리가 표시될 때까지 사용자 브랜치의 하위 브랜치들을 계속 확장하고, 서버 엔트리를 클릭한다. 이제 창의 오른쪽 패널에 있는 Infor 탭에 MBean에 관한 정보가 표시되어야 한다.

창의 오른쪽 패널에 있는 Attributes 탭을 클릭한 다음 EmailRecipientsString 속성을 위한 값 필드에 각자의 이메일 주소를 입력한다.

EmailRecipientsString 속성을 변경하면 이벤트 소스 커스텀 MBean이 통지를 발송하는데, 이 때 AttributeChangeNotification 클래스에 의해 정의되는 통지를 청취하고 이 속성의 새 값을 가져온다. 다음은 이 작업과 관련한 EventSinkCustom 내의 코드이다.

AttributeChangeNotification attrnotif = (AttributeChangeNotification) notif; String newEmailIdStr = (String)attrnotif.getNewValue();

이어서 이벤트 싱크 커스텀 MBean이 업데이트된 주소로 이메일을 전송한다.

9단계: 이메일 확인하기

리스닝 커스텀 MBean이 각자의 주소로 이메일을 전송했는지 확인하기 위해 우선 이메일을 살펴본다. 다음과 같은 메시지가 수신되어야 한다.

This message has been generated and sent as part of the Glassfish Techtip sample example execution

더 자세한 내용은 다음 사이트를 참조할 것.

저자 소개

Nandini Ektare는 썬 마이크로시스템즈의 썬 자바 시스템 애플리케이션 서버 개발 그룹 소속으로, JMX와 Java EE이 그녀의 주요 관심 분야이다.

Kedar Mhaswade는 썬 마이크로시스템즈의 스태프 엔지니어로, JSR 003: Java Management Extensions 전문가 그룹의 일원이다. 그의 주요 관심 분야로는 오픈소스 소프트웨어, JMX, Java EE 등이 있다.

맨위로

본 메일은 수신을 동의한 회원님에게만 발송됩니다.
본 메일의 수신을 거부하거나 수신주소를 변경하려면 SKDN@Sun.com으로 문의 주시기 바랍니다.

SKDN(Sun Korea Developers Network)에서 J2EE/J2SE 테크팁 등 다양한 아티클들을 참고하세요.

Copyright 2003-2006 Sun Korea, Ltd. All rights reserved.


'JAVA > JEE' 카테고리의 다른 글

[java mail] access to default session denied 에러발생시...  (1) 2007.07.05
http://xfire.codehaus.org/  (0) 2006.11.01
[펌]JMS(Java Messaging System)  (0) 2006.02.06
[링크] Oracle sample-code  (0) 2005.08.19
[링크]SmartClient  (0) 2005.08.10
Posted by tornado
|
Core Java Technologies Technical Tips
 Core Java Technologies Tech Tip에 오신 여러분을 환영합니다
Core Java Technologies
TECHNICAL TIPS
2006년 5월 12일자
 
<5월 개발자 이벤트>

썬 자바 스튜디오 크리에이터 무료 체험 및 웍스테이션 파격가 한정 판매

   설문에 참여하시고 PSP, 아이팟 등 푸짐한 선물을 받아가세요!!!
   자세한 내용 보기 »

5월의 Sun Technology Day - University Sun Day

   일시: 2006년 5월 23일(화) 10:00-14:00
   장소: 서울 대학교 제2공학관(302동) 105호
   주제: 자바의 현재와 미래, 오픈 솔라리스, 코드 캠프
   자세한 내용 보기 »

  이번 호에서는,

» 빈에서 Indexed Property 변경 사항 보고하기
» J2SE 5.0에서의 Java 2D API 기능 강화

에 대해 다룹니다.

이 문서는 Java 2 Platform, Standard Edition Development Kit 5.0 (JDK 5.0)을 기반으로 개발되었습니다. PDF 파일받기    

빈에서 Indexed Property 변경 사항 보고하기
 

J2SE 5.0의 JavaBeans 컴포넌트 API에 여러 다양한 기능들이 추가되었는데, IndexedPropertyChangeEvent에 대한 지원도 그 중 하나이다. JavaBeans 컴포넌트 API는 JavaBeans 컴포넌트(JavaBean 또는 그냥 '빈'이라고도 한다)의 Regular Property에 대한 변경 내용을 보고하는 수단을 제공했었는데, IndexedPropertyChangeEvent에 대한 지원으로 빈의 Indexed Property 변경에 관한 추가 정보를 보고하는 기능이 부가되었다.

대부분의 개발자들은 JavaBean 컴포넌트 속성에 관해 익숙한 편이다. 즉, 각자의 클래스에 set과 get 메소드를 간단히 추가하기만 하면 set과 get 다음의 이름에 의해 정의되는 읽기/쓰기 속성을 설정할 수 있다. 다시 말해, 클래스가 setName()getName()으로 명명된 메소드를 가지고 있다면 이 클래스는 name이라는 이름의 JavaBean 컴포넌트 속성을 가지게 된다.

컴포넌트 속성에는 Regular와 Indexed의 두 종류가 있는데, Indexed Property는 각각의 값이 Index에 의해 액세스되는 복수의 값을 가진다는 점에서 Regular Property와 구분된다. 한편 name과 같은 Regular Property를 위한 set과 get 메소드는 다음과 같은 형태를 띠게 된다.

Regular Property:
  • public void setName(String name)
  • public String getName()
name이 Indexed Property인 경우에 메소드는 다음과 같다.

Indexed Property:
  • public void setName(int index, String name)
  • public String getName(int index)
  • public void setName(String[] names)
  • public String[] getName()
빈은 속성값의 변경사항이 사용자에게 통지되도록 설계될 수 있으며, addPropertyChangeListener() 메소드를 이용하여 PropertyChangeListener 오브젝트를 빈에 등록할 수도 있다. 이 경우 PropertyChangeEvent 오브젝트나 IndexedPropertyChangeEvent 오브젝트를 통해 리스너에 변경 사항이 통지된다. 값 변경 시 PropertyChangeEvent를 생성하는 속성을 Bound Property라고 한다.

PropertyChangeListener 클래스는 다음과 같이 하나의 메소드를 가진다.
public void propertyChange(PropertyChangeEvent pce)그렇다면 propertyChange()에 대한 인자가 PropertyChangeEvent 타입인 경우에는 IndexedPropertyChangeEvent를 어떻게 통지받게 되는가? 그 대답은 IndexedPropertyChangeEvent 클래스가 PropertyChangeEvent의 서브클래스라는 사실에서 찾아볼 수 있다. 따라서, propertyChange()의 내부에서는 어떤 타입의 인자를 얻는지 확인하기 위한 instanceof 체크가 필요하다.

public void propertyChange(PropertyChangeEvent pce) { String name = pce.getPropertyName(); if (pce instanceof IndexedPropertyChangeEvent) { IndexedPropertyChangeEvent ipce = (IndexedPropertyChangeEvent) pce; int index = ipce.getIndex(); System.out.println("Property: " + name + "; index: " + index); } else { System.out.println("Property: " + name); } System.out.println("; value: " + pce.getNewValue()); }IndexedPropertyChangeEvent를 사용하는 예제 프로그램을 살펴보기에 앞서 Bound Indexed Property에 대한 변경을 보고하는 방법에 초점을 맞추어 보도록 하자. 다음은 앞서 살펴본 Name Indexed Propterty의 업데이트를 보고하는 코드이다.

private PropertyChangeSupport changeSupport; public ClassConstructor() { changeSupport = new PropertyChangeSupport(this); } public void setName(int index, String name) { String oldName = this.name; this.name = name; changeSupport.fireIndexedPropertyChange("name", index, oldName, name); }PropertyChangeSupport 클래스는 java.beans 패키지(JavaBeans 컴포넌트 API 패키지)에 들어 있는 지원 클래스이고, fireIndexedPropertyChange() 메소드는 Bound Indexed Property(이 경우에는 name)에 대한 변경을 addPropertyChangeListener() 메소드를 통해 등록된 모든 리스너에게 보고한다.

다음은 전체 예제의 내용이다.
import java.beans.*; import java.util.*; public class IndexedSampleBean { private PropertyChangeSupport changeSupport; private Map<Integer, String> names; private String title; public IndexedSampleBean() { changeSupport = new PropertyChangeSupport(this); names = new HashMap<Integer, String>(); } public void setTitle(String title) { String oldTitle = this.title; this.title = title; changeSupport.firePropertyChange("title", oldTitle, title); } public String getTitle() { return title; } public void setName(int index, String name) { String oldName = names.get(index); names.put(index, name); changeSupport.fireIndexedPropertyChange("name", index, oldName, name); } public String getName(int index) { return names.get(index); } public void addPropertyChangeListener( PropertyChangeListener l) { changeSupport.addPropertyChangeListener(l); } public void removePropertyChangeListener( PropertyChangeListener l) { changeSupport.removePropertyChangeListener(l); } public static void main(String[] args) throws Exception { IndexedSampleBean bean = new IndexedSampleBean(); PropertyChangeListener listener = new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent pce) { String name = pce.getPropertyName(); if (pce instanceof IndexedPropertyChangeEvent) { IndexedPropertyChangeEvent ipce = (IndexedPropertyChangeEvent) pce; int index = ipce.getIndex(); System.out.print("Property: " + name + "; index: " + index); } else { System.out.print("Property: " + name); } System.out.println("; value: " + pce.getNewValue()); } }; bean.addPropertyChangeListener(listener); bean.setName(1, "John"); bean.setName(2, "Ed"); bean.setName(3, "Mary"); bean.setName(4, "Joan"); bean.setTitle("Captain"); System.out.println("Name at 3 is: " + bean.getName(3)); System.out.println("Title is: " + bean.getTitle()); } }클래스는 name으로 명명된 Indexed Property를 정의하고 4개의 위치에서 name을 설정한다. 이와 함께 title로 명명된 Regular Bound Property 역시 생성되어 설정된다. 리스너는 이름이나 타이틀을 설정하고 이어서 속성 이름, 인덱스(해당될 경우), 값을 프린트하기 위한 각 호출을 통지받는다. 그러면 클래스는 특정 위치에서 이름을 얻고 단일 타이틀을 프린트하기 전에 이를 먼저 프린트한다.

프로그램을 실행하면 다음과 같은 결과가 나온다.
>java IndexedSample Property: name index: 1 value: John Property: name index: 2 value: Ed Property: name index: 3 value: Mary Property: name index: 4 value: Joan Property: title; value: Captain Name at 3 is: Mary Title is: CaptainJavaBeans component API에서의 IndexedPropertyChangeEvent 지원에 관한 자세한 내용은 J2SE 5.0의 JavaBeans Component API에 대한 API 강화를 참조하기 바란다. 자바 튜토리얼의 JavaBeans Trail도 함께 참조할 것.

맨위로

J2SE 5.0의 Java 2D API 기능 강화
 

자바 플랫폼 스탠다드 에디션의 버전이 새로 나올 때마다 크고 작게 기능이 개선되었다. 대부분의 사람들은 Generics나 새로운 병행 유틸리티(Concurrency Utilities) 패키지처럼 중요한 신기능에 관해서는 충분히 들어 내용을 잘 알고 있는 반면 자잘한 신기능들에 관한 정보를 입수할 수 있는 기회는 그다지 흔하지 않다. 또한 이런 기능들은 중요한 특성에 비해 소수의 사용자에게 유용하기 때문에 자주 언급되지도 않는다. 따라서 본 팁에서는 J2SE 5.0에 추가된 작지만 새로 강화된 Java 2D API 신기능들을 몇 가지 소개하고자 한다. 이러한 신기능은 각자의 운영체제와 하드웨어에 따라 실제 성능이 좌우되는 경우가 많으며, 경우에 따라서는 이러한 기능을 사용하는 것이 별 효과가 없을 수도 있다.

Bicubic Interpolation

Java 2D API에서 강화된 기능 중 하나는 이미지 스케일링에 관한 것으로, 회전을 비롯한 어파인 변형(Affine Transformation)에도 영향을 미친다. RenderingHints 클래스는 다양한 보간법(interpolation) 옵션을 처리하는 다음 2개의 상수를 가진다: VALUE_INTERPOLATION_BILINEARVALUE_INTERPOLATION_BICUBIC. KEY_INTERPOLATION 힌트를 2개 옵션 중 하나로 설정하면 기본 시스템이 이미지를 스케일링할 때 따라야 할 규칙이 지정된다. 한편, J2SE 5.0 이전까지는 2개의 힌트 값이 동일한 결과를 산출했다. RenderingHints는 단순한 힌트일 뿐이므로 무시해도 상관 없는데, 실제로 Bicubic 설정은 항상 무시되어 왔고, 대신 Bilinear Interpolation이 사용되었다.

2개의 보간법 옵션에 익숙치 않을 경우에는 이미지를 스케일업할 때 어떤 일이 벌어지는지 이해하면 상당한 도움이 된다. 예를 들어, 스케일업된 이미지의 새로운 픽셀들은 모두 어디서 나오는 것일까? Bilinear 스케일링의 경우 픽셀은 스케일된 픽셀에 가장 가까운 소스 이미지의 2x2 픽셀 직사각형에서 공급된다. 픽셀 직사격형은 X와 Y의 선형 함수를 이용하여 섞이게 되는데, Bicubic 스케일링의 경우 이들은 스케일된 픽셀을 둘러싼 4x4 면적에서 공급된다. 한편, 픽셀 직사각형은 X와 Y의 3차 함수를 이용하여 섞이게 된다. Bicubic 스케일링을 이용할 경우, 증가된 면적과 알고리즘의 복잡성으로 인해 스케일된 이미지의 품질을 향상되지만 대신 성능이 저하된다.

J2SE 5.0에서는 Bicubic 설정이 상당히 중시되는데, 다음의 테스트 프로그램을 실행해보면 이 사실을 알 수 있다. 프로그램을 실행할 때 이미지 파일을 지정한다. 프로그램은 RenderingHints를 2개의 상수 VALUE_INTERPOLATION_BILINEARVALUE_INTERPOLATION_BICUBIC으로 설정하고 보간법 알고리즘의 차이(있을 경우)를 보고한다. 먼저 JDK 1.4로 프로그램을 실행한 다음 JDK 5.0로 실행한다. 보간법 알고리즘의 차이는 신 버전의 JDK에서만 보고된다는 것을 알 수 있다.
import java.awt.*; import java.awt.image.*; import java.io.*; import javax.swing.*; import javax.imageio.*; public class Bicubic { public static void main(String args[]) throws IOException { if (args.length == 0) { System.err.println( "Provide image name on command line"); System.exit(-1); } Image image = ImageIO.read(new File(args[0])); int w = image.getWidth(null); int h = image.getHeight(null); BufferedImage bilinear = new BufferedImage(2*w, 2*h, BufferedImage.TYPE_INT_RGB); BufferedImage bicubic = new BufferedImage(2*w, 2*h, BufferedImage.TYPE_INT_RGB); Graphics2D bg = bilinear.createGraphics(); bg.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); bg.scale(2, 2); bg.drawImage(image, 0, 0, null); bg.dispose(); bg = bicubic.createGraphics(); bg.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); bg.scale(2, 2); bg.drawImage(image, 0, 0, null); bg.dispose(); for(int i=0; i<2*w; i++) for(int j=0; j<2*h; j++) if (bilinear.getRGB(i, j) != bicubic.getRGB(i, j)) System.out.println("Interpolation algo differ"); } } JDK 1.4 환경에서는 프로그램을 실행해도 아웃풋이 생성되지 않는다.
> java Bicubic image.jpg [No Output] JDK 1.5 환경에서는 차이가 있는 모든 픽셀이 보고된다.
> java Bicubic image.jpg Interpolation algo differ Interpolation algo differ Interpolation algo differ Interpolation algo differ Interpolation algo differ .... repeated many timesOpenGL 가속

2005년 3월 30일자 테크 팁 JOGL 개요에서는 OpenGL 3D 그래픽 API를 위한 자바 프로그래밍 언어 바인딩에 관해 설명한 바 있다. J2SE 5.0에는 2D API의 핵심 기능을 가속화하는 데 이용할 수 있는 몇 가지 GL 옵션이 포함되어 있는데, 이 옵션들은 '시트 밑에' 감추어져 있으므로 사용자는 OpenGL로 프로그래밍하는 방법을 알 필요가 없다. 가속 옵션은 기본적으로 "사용하지 않음" 상태로 설정되어 있고, 옵션을 사용하려면 sun.java2d.opengl 시스템 속성을 true로 설정하면 된다. OpenGL 기반 파이프라인과 관련하여 전송된 아웃풋을 verbose하고 싶으면 t 대신 True(대문자T) 값을 이용하고, 결과를 보려면 JDK에 포함된 Java 2D 데모 코드를 이용하면 된다.
java -Dsun.java2d.opengl=True -jar Java2Demo.jarOpenGL 기반의 파이프라인에 관한 자세한 내용은 Behind the Graphics2D: The OpenGL-based Pipeline을 참조할 것.

폰트 생성하기

J2SE 5.0 이전에는 Font 클래스를 이용하여 createFont() 메소드를 통해 InputStream에서 트루타입 폰트를 생성할 수 있었다.
public static Font createFont(int fontFormat, InputStream fontStream)이 때, fontFormatFont.TRUETYPE_FONT이다. J2SE 5.0의 경우 이 지원 항목에서 두 가지의 변경 사항이 있는데, 첫째는 Adobe Type 1 폰트를 생성할 수 있고, 두번째는 새로운 createFont() 메소드 시그니처를 통해 File 오브젝트에서 직접 폰트를 생성할 수 있다는 점이다.
public static Font createFont(int fontFormat, File fontFile)단순히 폰트를 설치하고자 한다면, 즉 어느 메소드로도 폰트를 생성할 생각이 없다면, $JREHOME/lib/fonts 디렉토리에 폰트 파일을 복사하면 된다. 그러면 폰트는 해당 디렉토리에 설치될 때 런타임 환경에 의해 자동으로 픽업된다.

이미지 가속(Acceleration)

Java 2D의 새로운 특징 중에서 마지막으로 살펴볼 내용은 이미지 가속에 관한 것이다. 이 기능들은 각 시스템의 기본 지원 여부에 의해 좌우되는데, 시스템이 이 기능들을 지원하지 않는다면 단순히 무시되어 버린다.

첫 번째 이미지 가속 기능은 버퍼된 이미지 캐싱인데, 비디오 메모리가 관리 이미지의 캐싱을 지원한다. 일반적으로, 관리 가능한 종류의 이미지를 사용하는 프로그램의 경우 관리되지 않는 이미지를 사용하는 프로그램에 비해 성능이 뛰어난 편이다. J2SE 5.0 이전에는 ComponentcreateImage() 메소드 또는 GraphicsConfigurationcreateCompatibleImage() 메소드를 통해 생성된 이미지만 Java 2D 구현에 의해 관리되었지만 이제는 BufferedImage 생성자 중 하나로 생성된 모든 이미지를 Java 2D 구현을 통해서도 관리할 수 있게 되었다.

또 하나의 새로운 이미지 가속 기능으로 이미지의 하드웨어 가속을 제어하는 능력을 들 수 있다. 하지만 J2SE 5.0에서는 이미지의 하드웨어 가속을 제어하는 데 사용되는 메소드가 완전하게 작동하지 않는다는 점에 유의할 필요가 있다. 자세한 내용은 이미지의 하드웨어 가속 제어를 위한 메소드를 참조하기 바란다.

이 지원의 가용성 여부는 이미지 컨텐트의 플랫폼과 타입에 의해 좌우되며, Microsoft Windows 플랫폼 상에서 결과를 보려면 경우에 따라 sun.java2d.translaccel 시스템 속성을 true로 설정해 주어야 한다. 플래그에 관한 자세한 내용을 보려면 Microsoft Windows 플랫폼을 위한 시스템 속성translaccel에 관한 설명을 참조할 것.

자바 프로그램 작성 시, 특정 이미지 연산을 최적화하기를 원한다는 것을 기본 시스템에 알려줄 수 있다. 이 작업은 시스템이 가속화된 메모리에 특정 이미지를 저장하는 방식의 우선순위 정함으로써 가능한데(가능한 경우 ), 여기서 '가능한 경우'라는 단서가 중요하다. J2SE 5.0 이전에는 VolatileImage 오브젝트가 가속화된 메모리에 저장되도록 요청할 수 있었는데, J2SE 5.0에서는 추가로 레귤러 Image 오브젝트를 그곳에 배치하도록 요청할 수 있게 되었다. 또한, 투명한 VolatileImage 오브젝트를 생성할 수도 있다 (이전에는 불투명한 오브젝트 생성만 가능했음).

getCapabilities() 메소드는 이제 VolatileImage로만 정의되는 것이 아니라 ImageVolatileImage 모두에 의해 정의되며, 이 메소드는 특정 이미지가 현재 가속화되고 있는지 확인하는 데 이용될 수도 있다. 또한 setAccelerationPriority() 메소드로 가속 우선순위를 지정하거나 getAccelerationPriority() 메소드로 우선순위 설정을 확인할 수 있다. 가속 우선순위가 0으로 되어 있는 경우에는 특정 이미지의 가속화 기능은 사용되지 않는다. 하지만 우선순위 설정은 단지 힌트일 뿐이며, JDK 구현은 적절한 판단 기준에 따라 이를 중시(또는 무시)할 수 있다.

투명한 VolatileImage 오브젝트를 생성하려면 두 가지의 새로운 createCompatibleVolatileImage() 메소드 중 하나를 이용해야 한다.
  • createCompatibleVolatileImage( int width, int height, int transparency)
  • createCompatibleVolatileImage( int width, int height, ImageCapabilities caps, int transparency)
요약

자바 플랫폼이 계속 발전함에 따라, 크게 주목을 끄는 주요 핵심 기능 이외의 사소한 특성들에 대해서도 관심을 가질 필요가 있다. 실례로, 솔라리스 및 Linux를 위한 CUPS(Common Unix Printer System) 프린터 지원 같은 작은 기능들이 소리 소문 없이 추가되었는데, 만약 사용자가 CUPS 프린터를 사용하고 있다면 이 새로운 기능이 상당히 중요한 역할을 하게 될 것이다. 따라서 평소에 원하던 기능이 새로 추가되지는 않았는지 릴리즈 노트를 잘 살펴보기 바란다. 아울러, J2SE 5.0의 새로운 특징과 강화된 기능에 대한 설명도 함께 참조할 것.

맨위로

본 메일은 수신을 동의한 회원님에게만 발송됩니다.
본 메일의 수신을 거부하거나 수신주소를 변경하려면 SKDN@Sun.com으로 문의 주시기 바랍니다.

SKDN(Sun Korea Developers Network)에서 J2EE/J2SE 테크팁 등 다양한 아티클들을 참고하세요.

Copyright 2003-2006 Sun Korea, Ltd. All rights reserved.


Posted by tornado
|

[qmail]queue-fix

OS/LINUX 2006. 5. 30. 15:41
김남일
손님





올리기올려짐: 2004년2월12일 2:19 pm    주제: queue-fix 설치는 어떻게 하나요. 인용과 함께 답변

스팸메일로 인하여 자꾸만 queue에 쌓이네요.
그래서 큐를 모두 지우고 다시 생성할려고 하는데
queue-fix.tar.gz를 다운로드 하였거든요.
그런데 어떻게 설치해야 될지 모르겠네요.
설치해 보신분 답변 부탁드립니다.
위로
'); // :badtag -->
 
김남일
손님





올리기올려짐: 2004년2월12일 3:17 pm    주제: Re: [자답] 해결했습니다. 인용과 함께 답변

자답입니다.
여기에 찾아보니까 있더군요.
해결했습니다

tar xzf queue-fix.tar.gz
cat ../queue-fix-1.4.diff | patch -p1
make
rm -rf /var/qmail/queue
./queue-fix -i /var/qmail/queue



김남일 wrote..
> 스팸메일로 인하여 자꾸만 queue에 쌓이네요.
> 그래서 큐를 모두 지우고 다시 생성할려고 하는데
> queue-fix.tar.gz를 다운로드 하였거든요.
> 그런데 어떻게 설치해야 될지 모르겠네요.
> 설치해 보신분 답변 부탁드립니다.
Posted by tornado
|