리모트 인터페이스를 구현한 클래스
인터페이스가 있으면 인터페이스를 구현한 클래스가 필요합니다.
네트워크 데이타베이스 서비스 인터페이스 NetworkMovieDatabase를 구현하는 클래스를
NetworkMovieDatabaseImpl로 부르겠습니다.
NetworkMovieDatabaseImpl클래스는 매우 간단하고,간명하게 구현할 수 있습니다.
왜냐하면 NetworkMovieDatabaseImpl 클래스는 실제 데이터베이스를 운영하는 서버에서
동작할 텐데, 네트워크 관련된 부분은 RMI에서 모두 처리해주고, 데이터베이스 관련한 부분
은 MovieDatabase를 이용하면 되기 때문입니다.
이 경우 NetworkMovieDatabaseImpl에서 하는 일이라고, Delegation하는 일 밖에 없습니다.
실제로 일을 하는 객체는 Delegation 당하는 MovieDatabase 객체입니다.
package network;
import java.rmi.*;
import java.rmi.server.*;
import java.io.IOException;
import java.util.*;
import movie.*;
/**
* 이 클래스는 네트워크 기반 데이타베이스 서버로 기본적인 데이타베이스 기능인
* 레코드 검색,추가,삭제,수정등의 서비스를 네트워크 기반으로 제공합니다.
*
* @author djkim
* @version 1.0
* @since 2003.05
*/
public class NetworkMovieDatabaseImpl
extends UnicastRemoteObject implements NetworkMovieDatabase {
/**
* 로컬 데이타베이스
*/
private MovieDatabase mdb = null;
/**
* 네트워크 데이타베이스 서비스객체를 생성합니다.
* @exception RemoteException
*/
public NetworkMovieDatabaseImpl() throws RemoteException {
super();
}
/**
* 네트워크 데이타베이스 서버가 위치한 곳의 데이타베이스 파일 dbname을 엽니다.
*
* @param String dbname 네트워크 데이타베이스의 데이타베이스 파일이름
* @exception IOException 네트워크 데이타베이스 서버가 데이타베이스 파일을
* 열지 못했을 때
* @exception RemoteException
*/
public void open(String dbname) throws RemoteException,IOException {
// 데이타베이스 파일 dbname으로 데이타베이스 생성
if (mdb == null)
mdb = new MovieDatabase(dbname);
}
/**
* 데이타베이스를 닫습니다.
* 데이타베이스를 닫은 후에는 데이타베이스로 정보를 읽거나 쓸수 없습니다.
*
* @exception RemoteException;
*/
public void close() throws RemoteException{
// 데이타베이스 파일 dbname을 닫습니다.
if (mdb != null)
mdb.close();
}
/**
* 데이타베이스 레코드의 칼럼 정보, 칼럼 정보는 칼럼 이름과 칼럼 길이입니다.
*
* @return Field[] 데이타베이스 레코드의 칼럼 정보
* @exception RemoteException
*/
public Field[] getFields() throws RemoteException {
return mdb.getFields();
}
/**
* 데이타베이스에 존재하는 레코드의 갯수를 구합니다.
*
* @return int 데이타베이스에 존재하는 레코드의 갯수
* @exception RemoteException
*/
public int getRecordCount() throws RemoteException {
return mdb.getRecordCount();
}
/**
* 데이타베이스로부터 recno번째 레코드를 구해냅니다.
* 레코드는 1번부터 시작합니다.
*
* @param recno recno번째 레코드
* @return Record recno번째 존재하는 레코드
* @exception DatabaseException 범위를 벗어난 레코드를 지정하는 경우
* recno번째 레코드가 데이타베이스에 없거나 삭제된 경우
* 데이타베이스로 읽기,쓰기가 안될때 등
* @exception RemoteException
*/
public Record getRecord(int recno)
throws DatabaseException ,RemoteException {
return mdb.getRecord(recno);
}
/*
* key값을 가진 레코드를 데이타베이스로 부터찾아냅니다.
* 레코드를 데이타베이스로부터 찾지 못할 경우 null을 리턴합니다.
* 레코드의 key값은 레코드가 가지는 여러개의 칼럼중에
* 첫번째 칼럼이 레코드의 key입니다.
*
* @exception DatabaseException 데이타베이스로 읽기,쓰기가 안될때등
* @return Record key값을 가진 레코드, key값을 가지는 레코드가 없을 경우 null
* @param key 레코드의 key 값
* @exception RemoteException
*/
public Record find(String key)
throws DatabaseException ,RemoteException {
return mdb.find(key);
}
/**
* query에 따라 데이타베이스를 검색하여 조건에 맞는 레코드를 리턴합니다.
* 조건에 맞는 레코드가 데이타베이스에 없다면 null을 리턴합니다.
* qeury는 comma로 분리된 name=value,name=value형태입니다.
* 예를 들어 query가 제목=반지의제왕,극장=명보극장 이라면 명보극장에서
* 상영하는 제목이 반지의제왕인 레코드들을 검색합니다.
*
* @return List 검색조건에 맞는 레코드들
* @param String query 레코드 검색조건입니다.
* comma로 분리된 name=value형태의 반복입니다.
* @exception DatabaseException 데이타베이스 파일을 읽을 수 없을때
* @exception RemoteException
*/
public List finds(String query)
throws DatabaseException, RemoteException {
return mdb.finds(query);
}
/**
* 데이타베이스에 한 레코드를 추가합니다.
*
* @param Record 데이타베이스에 추가할 레코드
* @exception DatabaseException 데이터베이스로 부터 읽기 쓰기가 안될때등
* @exception RemoteException
*/
public void add(Record record)
throws DatabaseException,RemoteException {
mdb.add(record);
}
/**
* 데이타베이스에 존재하는 Record객체를 수정합니다.
* 레코드를 수정하기 전에 반드시 레코드에 Lock을 얻어야 하고,
* 수정한 후에는 레코드 Lock을 해제해야만 합니다.
*
* @param record 수정하고 싶은 레코드
* @exception DatabaseException 데이타베이스에 읽기, 쓰기가 안될때 등
* @exception RemoteException
*/
public void modify(Record record)
throws DatabaseException,RemoteException {
try {
/* record에 대한 lock을 얻어야 합니다.*/
mdb.lock(record.getRecno());
mdb.modify(record);
}
catch(IOException ie) {
throw new DatabaseException(ie.getMessage());
}
finally {
/* record에 대한 lock을 얻었다면 반드시 lock을 해제해야 합니다.*/
mdb.unlock(record.getRecno());
}
}
/**
* 데이타베이스의 key에 해당되는 특정 레코드를 삭제표시합니다.
* 레코드를 삭제하기 전에 반드시 레코드에 Lock을 얻어야 하고,
* 삭제한 후에는 레코드 Lock을 해제해야만 합니다.
*
* @param String key 특정 레코드의 키값
* @exception DatabaseException 데이타베이스로 읽기쓰기가 안될때등
* @exception RemoteException;
*/
public void delete(String key) throws DatabaseException ,RemoteException {
Record record = null;
try {
record = find(key);
if (record != null){
/* 레코드에 대해서 반드시 lock을 얻어야합니다.*/
mdb.lock(record.getRecno());
mdb.delete(key);
}
}
catch(IOException ie) {
throw new DatabaseException(ie.getMessage());
}
finally {
/* 레코드에 대해서 lock을 얻었다면 반드시 해제해야합니다.*/
if (record != null)
mdb.unlock(record.getRecno());
}
}
/**
* 이 메소드는 지정한 레코드(영화)에 대해 하나 이상의 표를 예매합니다.
* 이 메소드는 다중 thread 환경에서 사용되므로 locking기능을 반드시
* 포함해야만 합니다. 조건에 맞는 영화표가 없을 경우는 적절한 메세지를 포함한
* DatabaseException을 throw 합니다.
* @param int recno : 예약하고자 하는 영화에 대한 레코드 번호 (레코드 위치)
* @param int seats : 예약하고자 하는 영화표 갯수
* @exception DatabaseException 예약하고자 하는 영화표가 부족할때
* @exception RemoteException
*/
public void book(int recno,int seats)
throws DatabaseException,RemoteException {
try {
/* recno번호 레코드에 대한 lock을 얻습니다.*/
mdb.lock(recno);
mdb.book(recno,seats);
}
catch(IOException ie) {
throw new DatabaseException(ie.getMessage());
}
finally {
/* recno번호 레코드에 대한 lock을 반드시 해제합니다.*/
mdb.unlock(recno);
}
}
public static void main(String[] args) throws Exception {
/* 네트워크 기반 데이타베이스 서버 생성 */
NetworkMovieDatabaseImpl nmdb = new NetworkMovieDatabaseImpl();
/* RMI Registery에 database라는 이름으로 등록 */
Naming.rebind("database",nmdb);
System.out.println("클라이언트로 부터 서비스 요청이 있기를 기다립니다...");
}
}
예제 18 - 12 NetworkMovieDatabaseImpl.java
NetworkMovieDatabaseImpl은 public static void main(String[] args) 메소드를 가지고
있는데 이유는 RMI 레지스트리에 RMI 서버 객체를 등록하기 위해서 입니다.
RMI 레지스트리에 등록하는 객체는 NetworkMovieDatabaseImpl 객체이고,
바인딩되는 이름은 "database"입니다.
네트워크 데이타베이스 객체의 서비스를 받고자하는 네트워크 클라이언트는
RMI 레지스트리에서 "database"라는 이름으로 객체를 찾아야 할 것입니다.
클라이언트도 반드시 알고 있어야하는 이름입니다. 일단 "database"라는 이름으로
객체를 찾으면 그 객체를 NetworkMovieDatabase 인터페이스와 바인딩하여
RMI 메소드를 호출할 수 있습니다. 네트워크로 데이타베이스 서비스를 받을 수
있다는 뜻입니다.
Naming.rebind() 메소드는 Naming클래스의 static 메소드인데 RMI 레지스트리에
"database"라는 이름으로 객체가 등록되어 있다면 기존에 등록되어 있는 객체가
무엇이든간에 "database"라는 이름으로는 새로운 객체로 등록합니다.
결국 여기서는 "database"라는 이름으로 "NetworkMovieDatabaseImpl" 객체가
등록됩니다.
NetworkMovieDatabaseImpl은 네트워크 관련된 내용은 RMI 를 이용하고,
데이타베이스 관련된 내용은 MovieDatabase객체를 이용하는 네트워크 서버입니다.
'자바 SCJD Projects' 카테고리의 다른 글
SCEJ(SCEA) 후기 (0) | 2008.09.23 |
---|---|
SCJD-6.리모트 인터페이스 (0) | 2008.01.21 |
SCJD-5.검색과 레코드 Locking (0) | 2007.12.24 |
SCJD-4.확장 데이타베이스의 구조와 기능 (0) | 2007.12.18 |
SCJD-3. 기본 클래스 (0) | 2007.12.13 |