Java IDL:콜백 객체를 사용하는 예 - xrath.com 에서 번역됨

# Java IDL:콜백 객체를 사용하는 예

클라이언트 프로그램에서는, 서버측에서 일어난 변경이나 갱신에의 대응이 필요하게 되는 일이 있습니다. 예를 들어, 주가 서버상에서 주가가 갱신될 때마다, 클라이언트의 그래프 표시 프로그램이나 스프레드쉬트 프로그램에서도 갱신을 실시하고 싶다고 했을 경우 등입니다. 이러한 경우, 클라이언트에는

- 주가 서버상의 메소드를 정기적으로 호출해 주가를 물어 합 깬다. 이것을, 「폴링」모델 또는 「풀」모델이라고 한다
- 주가가 갱신될 때마다 통지하도록(듯이) 서버에 요구한다. 이것을, 「콜백」모델 또는 「푸쉬」모델이라고 한다

이 문서의 예에서는, 클라이언트 프로그램으로부터 서버에 콜백 객체를 건네주는 방법과 그 후에 서버로부터 클라이언트로 변경을 통지하는 방법에 대해 설명합니다. 여기에서는, 단순한 어플리케이션을 확장한 코드를 소개합니다. 어플리케이션을 간략화한 개소에 대해서는, 코드내에 코멘트를 기재합니다.

이 문서로 소개하는 코드는, 다음과 같은 것입니다.

- 콜백을 사용하는 샘플 프로그램의 IDL
- 클라이언트에 콜백을 실시하는서버의 구현
- 콜백 객체 참조를 서버에 보내는클라이언트
- `Listener` 의 구현
- `MessageServer` 의 구현

컴파일 방법과 실행 방법에 대한설명 프로그램예도 준비되어 있습니다.

# 콜백의 예:중급 레벨

## IDL 파일의 기술

이 어플리케이션예로 사용하는 `callback.idl` 파일은, 다음과 같은 것입니다.

    interface Listener {
    	void message(in string msg);
    };

    interface MessageServer {
    	void register(in Listener lt);
    };

## 서버 코드의 기술

이 어플리케이션예로 사용하는 `Server.java` 파일은, 다음과 같은 것입니다.

    import org.omg.CORBA.ORB;
    import org.omg.PortableServer.POA;
    import org.omg.PortableServer.POAHelper;
    import org.omg.CosNaming.NameComponent;
    import org.omg.CosNaming.NamingContext;
    import org.omg.CosNaming.NamingContextHelper;

    public class Server {

        public static void main(String[] args) {
    	try {
                //create and initialize the ORB
                Properties props = System.getProperties();
                props.put("org.omg.CORBA.ORBInitialPort", "1050");
                //Replace MyHost with the name of the host on which you are running the server
                props.put("org.omg.CORBA.ORBInitialHost", "<MyHost>");
                ORB orb = ORB.init(args, props);
    	    System.out.println("Initialized ORB");

                //Instantiate Servant and create reference
    	    POA rootPOA = POAHelper.narrow(
    		orb.resolve_initial_references("RootPOA"));
    	    MessageServerImpl msImpl = new MessageServerImpl();
    	    rootPOA.activate_object(msImpl);
    	    MessageServer msRef = MessageServerHelper.narrow(
    		rootPOA.servant_to_reference(msImpl));

                //Bind reference with NameService
    	    NamingContext namingContext = NamingContextHelper.narrow(
    		orb.resolve_initial_references("NameService"));
                System.out.println("Resolved NameService");
                NameComponent[] nc = { new NameComponent("MessageServer", "") };
    	    namingContext.rebind(nc, msRef);

    	    //Activate rootpoa
                rootPOA.the_POAManager(). activate();

                //Start readthread and wait for incoming requests
                System.out.println("Server ready and running ....");

                //REMOVE THE NEXT LINE FOR THE SIMPLER EXAMPLE
                msImpl.startReadThread();

                orb.run();

    	} catch (Exception e) {
    	    e.printStackTrace();
    	}
        }
    }

## MessageServer 구현의 기술

이 파일의 코드에서는, 새로운 클라이언트를 등록해, 메세지를 받아들인 후, 등록된 클라이언트에 그 메세지를 중계합니다. 이 어플리케이션예로 사용하는 `MessageServerImpl.java` 파일은, 다음과 같은 것입니다.

    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    import java.util.Vector;
    import java.util.Iterator;

    public class MessageServerImpl extends MessageServerPOA {

        private Vector clients = new Vector();
        private ReadThread rt = null;

        public MessageServerImpl() {
    	rt = new ReadThread(this);
        }

        public void register(Listener lt) {
    	clients.add(lt);
        }

        public void startReadThread() {
            rt.start();
        }

        public void message(String msg) {
    	Iterator it = clients.iterator();
    	while (it.hasNext()) {
    	    Listener lt = (Listener) it.next();
    	    lt.message(msg);
    	    //FOR THE SIMPLER EXAMPLE, ADD A SIMPLE
    	    //MESSAGE TO BE CALLED BACK, FOR EXAMPLE,
    	    //SLEEP FOR 30 SECONDS, THEN SEND THE TIME
    	}
        }
    }

    //EXCLUDE THIS CLASS FOR THE SIMPLER EXAMPLE
    class ReadThread extends Thread {

        MessageServerImpl msImpl = null;

        public ReadThread(MessageServerImpl msImpl) {
    	this.msImpl = msImpl;
        }

        public void run() {
    	BufferedReader br = new BufferedReader(
    	    new InputStreamReader(System.in));

            try {
    	    for (;;) {
                    System.out.print("message > ");
    		String msg = br.readLine();
    		msImpl.message(msg);
    	    }
    	} catch (Exception e) {
    	    e.printStackTrace();
    	}
        }
    }

## 클라이언트 코드의 기술

이 어플리케이션예로 사용하는 `Client.java` 파일은, 다음과 같은 것입니다.

    import java.util.Properties;
    import org.omg.CORBA.ORB;
    import org.omg.PortableServer.POA;
    import org.omg.PortableServer.POAHelper;
    import org.omg.CosNaming.NameComponent;
    import org.omg.CosNaming.NamingContext;
    import org.omg.CosNaming.NamingContextHelper;

    public class Client {

        public static void main(String[] args) {
    	try {

                //initialize orb
                Properties props = System.getProperties();
                props.put("org.omg.CORBA.ORBInitialPort", "1050");
                //Replace MyHost with the name of the host on which you are running the server
                props.put("org.omg.CORBA.ORBInitialHost", "<MyHost>");
                ORB orb = ORB.init(args, props);
    	    System.out.println("Initialized ORB");

                //Instantiate Servant and create reference
    	    POA rootPOA = POAHelper.narrow(
    		orb.resolve_initial_references("RootPOA"));
                ListenerImpl listener  = new ListenerImpl();
                rootPOA.activate_object(listener);
    	    Listener ref = ListenerHelper.narrow(
                    rootPOA.servant_to_reference(listener));

                //Resolve MessageServer
    	    MessageServer msgServer = MessageServerHelper.narrow(
    	        orb.string_to_object("corbaname:iiop:1. 2@localhost:1050#MessageServer"));

                //Register listener reference (callback object) with MessageServer
                msgServer.register(ref);
                System.out.println("Listener registered with MessageServer");

    	    //Activate rootpoa
                rootPOA.the_POAManager(). activate();

                //Wait for messages
                System.out.println("Wait for incoming messages");
                orb.run();

    	} catch (Exception e) {
    	    e.printStackTrace();
    	}
        }
    }

## Listener 구현의 기술

Listener 는, 서버로부터의 메세지 수신을 식별하면(자), 그 메세지를 클라이언트에 표시합니다. 이 어플리케이션예로 사용하는 `ListenerImpl.java` 파일은, 다음과 같은 것입니다.

    public class ListenerImpl extends ListenerPOA {

        public void message(String msg) {
    	System.out.println("Message from server : " + msg);
        }
    }

## 샘플의 컴파일 방법과 실행 방법에 대한 설명

이 어플리케이션예를 실행하려면 , 이하의 순서를서버머신으로 실행합니다.

1. 예를 이전에 실행했던 적이 있는 경우는, 생성된 기존의 파일을 삭제합니다. UNIX 오퍼레이팅(operating) 환경에서는, 다음과 같은 커멘드를 사용합니다.

       rm -rf . /classes . /orb.db

2. Stub와 스켈리턴을 생성합니다. 우선, Stub와 스켈리턴을 두는 디렉토리를 작성해, 다음에,`idlj` 컴파일러를 실행해 Stub와 스켈리턴을 생성합니다. 커멘드는 다음과 같이 됩니다.

       mkdir -p . /classes
       <path_to_java>/bin/idlj -fall -td . /classes callback.idl

3. 다음과 같이 해,`. java` 파일을 컴파일 합니다.

       <path_to_java>/bin/javac -classpath . /classes -d . /classes *. java

4. 다음과 같이 해,`orbd` 네임 서비스를 개시합니다.

       <path_to_java>/bin/orbd -ORBInitialPort 1050 -ORBInitialHost <host_name> &

5. 다음과 같이 해, 서버를 실행합니다.

       <path_to_java>/bin/java -classpath . /classes Server -ORBInitialPort 1050

서버를 개시하면(자), 단말 윈도우에 다음과 같은 출력이 표시됩니다.

    Initialized ORB
    Resolved NameService
    Server ready and running ....
    message >

이 prompt를 사용해 클라이언트에 메세지를 송신하게 됩니다만, 그 전에, 클라이언트 어플리케이션을 개시할 필요가 있습니다. 클라이언트의 단말로 다음의 순서를 실행해, 클라이언트 어플리케이션을 실행합니다. 클라이언트 코드의 properties 섹션으로, 서버가 실행되고 있는 호스트명을 사용한 것을 확인해 주세요.

    <path_to_java>/bin/java -classpath . /classes Client -ORBInitialPort 1050

클라이언트 어플리케이션으로부터의 출력이, 다음과 같은 형식에서 표시됩니다.

    Initialized ORB
    Listener registered with MessageServer
    Wait for incoming messages

콜백을 사용한 기능을 표시하려면 , 서버 단말의 prompt에 데이터를 입력합니다. 그렇다면, 그 데이터가 모든 클라이언트 단말에 표시됩니다. 통지의 내용에는, 클라이언트가 관심을 가지는 것을 뭐든지 포함할 수가 있습니다.

일례로서 풋볼의 시합의 스코아가 변화했을 때에, 클라이언트에 통지해 보겠습니다.

    message > Niners TD.  Niners 7 - Giants 0
    message > Giants TD.  Niners 7 - Giants 7
    message > Niners TD.  Niners 14 - Giants 7

상기와 같은 메세지가 송신되면(자), 클라이언트에 다음과 같이 표시됩니다.

    Wait for incoming messages
    Message from server : Niners TD.  Niners 7 - Giants 0
    Message from server : Giants TD.  Niners 7 - Giants 7
    Message from server : Niners TD.  Niners 14 - Giants 7

홈

Copyright © 2002-2004 Sun Microsystems, Inc. All Rights Reserved.