Java IDL:ImplBase 서버측 모델을 사용한 「Hellow World」의 예 - xrath.com 에서 번역됨

# Java IDL:ImplBase 서버측 모델을 사용한 「Hellow World」의 예

이 문서는, 인터페이스를 정의하는 IDL (Interface Definiton Language)와 Stub 및 스켈리턴을 생성하는 Java IDL 컴파일러를 사용해, 완전한 CORBA (Common Object Request Broker Architecture) 어플리케이션을 작성하는 방법에 대해, 고레벨의 개요를 설명한 것입니다. 이 문서에서는, ImplBase 상속 서버측 모델의 사용법을 설명합니다.

`idlj` 컴파일러는 POA 상속 모델에 근거하는 서버측 매핑을 디폴트로 생성합니다. 기존의 어플리케이션과의 호환성을 유지하기 (위해)때문에,`idlj` 컴파일러에 새로운 플래그 `-oldImplBase` 를 추가해, ImplBase 상속 모델에 근거하는 서버측 매핑을 작성할 수가 있습니다. J2SE 버젼 1.3 이전에 작성한 서버와 접속할 필요가 있는 기존의 어플리케이션은, MAKEFILE 를 갱신해 이 플래그를 이용할 수 있도록(듯이) 할 필요가 있습니다. 다만, 그러한 요구가 없는 신규 어플리케이션에서는 이러한 매핑은 작성하지 않는 것을 추천합니다.

주: ImplBase 는 POA 모델이 있으므로 추천 되지 않습니다만, 버젼 1.3 이전의 J2SE 로 기술된 서버와 호환성을 가지기 위해서(때문에) 제공되고 있습니다. 이것은 비표준 모델이므로, 이것을 사용해 새로운 서버를 작성하는 것은 추천하지 않습니다.

이 문서에서는, 다음의 내용에 대해 설명합니다.

- 단순한 「Hello World」프로그램의 IDL
- 객체를 작성하는서버 ImplBase 서버측 구현 (POA)을 사용하는 네이밍 서비스와 함께 객체를 발행
- 기존의 객체명의 객체 참조를 네이밍 서비스로부터 찾아, 그 객체를 호출하는어플리케이션 클라이언트
- 컴파일 방법과 실행 방법에 대한설명 례

## 인터페이스 정의 (`Hello.idl`)

CORBA 어플리케이션 작성의 제일 단계는, OMG 의 인터페이스 정의 언어 (IDL)를 사용해, 객체와 인터페이스를 모두 기술하는 것입니다. IDL 에는 C++ 를 닮은 구문이 있어, 이것을 사용해 모듈, 인터페이스, 데이터 구조등을 정의할 수가 있습니다. IDL 는 다양한 프로그램 언어에 매핑 할 수 있습니다. IDL 를 Java 에 매핑 하는 방법은「IDL 와 Java 언어의 매핑의 개요」로 설명하고 있습니다.

다음의 코드는 OMG IDL 로 기술된 것으로, CORBA 객체의 `sayHello()` 오퍼레이션이 캐릭터 라인을 돌려주어 `shutdown()` 오퍼레이션이 ORB 를 지 그런데 있습니다. OMG IDL 의 구문과 시멘틱스의 자세한 것은, OMG 의 Web 사이트에서 CORBA Specification 의 제 3 장을 참조해 주세요.

Hello.idl

    module HelloApp
    {
      interface Hello
      {
      string sayHello();
      oneway void shutdown();
      };
    };

주: OMG IDL 로 코드를 기술하는 경우, 모듈명에 인터페이스명을 사용하지 말아 주세요. 모듈명에 인스턴스명을 사용하면(자), 다른 벤더의 툴을 사용한 컴파일 실행시에, 결과의 무결성이 유지되지 않게 되는 위험이 있습니다. 그 결과, 코드의 이식성이 손상됩니다. 예를 들어, 같은 이름을 포함한 코드를 Sun Microsystems 의 IDL-to-Java 컴파일러를 사용해 컴파일 하면(자), 1 개의 결과를 얻을 수 있습니다. 같은 코드를 다른 벤더의 IDL-to-Java 컴파일러를 사용해 컴파일 하면(자), 다른 결과가 되는 경우가 있습니다.

어플리케이션을 완성 지난에는, 서버 (`HelloServer.java`)와 클라이언트 (`HelloClient.java`)를 구현합니다.

## 서버의 구현 (`HelloServer.java`)

여기서 소개하는 서버는, 서번트와 서버의 2 개의 클래스로 구성됩니다 . 서번트인 `HelloImpl` 는, IDL 인터페이스 `Hello` 의 구현입니다. 즉,`Hello` 의 각 인스턴스는, `HelloImpl` 의 인스턴스에 의해 구현됩니다. 이 서번트는 idltojava 컴파일러에 의해 상기의 IDL 로부터 생성되는 `_HelloImplBase` 의 서브 클래스입니다. 예제 IDL 로부터 `idlj` 컴파일러에 의해 생성됩니다. 서번트에게는, IDL 의 오퍼레이션 마다 1 개의 메소드가 포함됩니다. 이 예에서는 `sayHello()` 메소드와 `shutdown()` 메소드가 포함됩니다. 서번트 메소드는, Java 의 일반적으로의 메소드와 다르지 않습니다. ORB 관련 처리를 실시하는 코드는 인수나 결과의 정렬화등을 실시해, 스켈리턴으로 제공됩니다.

`HelloServer` 클래스에는 서버의 `main()` 메소드가 포함됩니다. 이 `main()` 메소드에서는, 다음의 처리를 실시합니다.

- ORB 의 인스턴스를 생성해 초기화한다
- 서번트의 인스턴스 (1 개의 CORBA `Hello` 객체의 구현)(을)를 생성해, 그것을 ORB 에게 전한다
- 네이밍 문맥의 CORBA 객체 참조를 취득해, 새로운 CORBA 객체를 등록한다
- 루트의 네이밍 문맥을 취득한다
- 새로운 객체를 「Hello」라고 하는 이름으로 네이밍 문맥에 등록한다
- 클라이언트로부터 새로운 객체가 불려 가는 것을 기다린다

주: ImplBase 는 POA 모델이 있으므로 추천 되지 않습니다만, 버젼 1.3 이전의 J2SE 로 기술된 서버와 호환성을 가지기 위해서(때문에) 제공되고 있습니다. 이것은 비표준 모델이므로, 이것을 사용해 새로운 서버를 작성하는 것은 추천하지 않습니다.

ImplBase 서버측 구현의 `HelloServer` 는, POA 구현의 경우와는 조금 다릅니다. 루트 POA 의 참조를 취득해 `POAManager` 를 기동하는 POA 베이스의 서버의 섹션은 필요 없습니다. 다음과 같이 됩니다.

HelloServer.java

    // Copyright and License
    import HelloApp. *;
    import org.omg.CosNaming. *;
    import org.omg.CosNaming.NamingContextPackage. *;
    import org.omg.CORBA. *;

    import java.util.Properties;

    class HelloImpl extends _HelloImplBase{

      private ORB orb;

      public void setORB(ORB orb_val){
        orb = orb_val;
      }

      public String sayHello(){
        return "\nHello world !!\n";
      }

      public void shutdown(){
        orb.shutdown(false);
      }
    }

    public class HelloServer {

      public static void main(String args[]) {
        try{
          // create and initialize the ORB
          ORB orb = ORB.init(args, null);

          // create servant and register it with the ORB
          HelloImpl helloImpl = new HelloImpl();
          helloImpl.setORB(orb);

          // get the root naming context
          org.omg.CORBA.Object objRef =
              orb.resolve_initial_references("NameService");
          NamingContext ncRef = NamingContextHelper.narrow(objRef);

          Hello href = HelloHelper.narrow(helloImpl);

          // bind the Object Reference in Naming
          NameComponent nc = new NameComponent("Hello", "");
          NameComponent path[] = {nc};
          ncRef.rebind(path, href);

          System.out.println("HelloServer ready and waiting ...");

          // wait for invocations from clients
          orb.run();
        }

        catch (Exception e) {
          System.err.println("ERROR: " + e);
          e.printStackTrace(System.out);
        }

        System.out.println("HelloServer Exiting ...");

      }
    }

## 클라이언트 어플리케이션의 구현 (`HelloClient.java`)

후술의 어플리케이션 클라이언트의 예는디폴트의 튜토리얼로 가리킨 것과 닮아 있습니다만, 이 예에서는 하위 호환성을 유지하는 신기능의 Interoperable Naming Service 는 사용되고 있지 않습니다. 클라이언트 어플리케이션의 예:

- ORB 를 생성해 초기화한다
- 네이밍 문맥에의 참조를 취득한다
- 네이밍 문맥으로부터 「Hello」를 찾아, 그 CORBA 객체에의 참조를 받는다
- 객체의 `sayHello()` 및 `shutdown()` 오퍼레이션을 호출해, 결과를 출력한다

HelloClient.java

    // Copyright and License

    import HelloApp. *;
    import org.omg.CosNaming. *;
    import org.omg.CosNaming.NamingContextPackage. *;
    import org.omg.CORBA. *;

    public class HelloClient{

      static Hello helloImpl;

      public static void main(String args[]){

        try{
          // create and initialize the ORB
          ORB orb = ORB.init(args, null);

          // get the root naming context
          org.omg.CORBA.Object objRef =
    	  orb.resolve_initial_references("NameService");
          NamingContext ncRef = NamingContextHelper.narrow(objRef);

          // resolve the Object Reference in Naming
          NameComponent nc = new NameComponent("Hello", "");
          NameComponent path[] = {nc};
          Hello helloImpl = HelloHelper.narrow(ncRef.resolve(path));

          System.out.println("Obtained a handle on server object: " + helloImpl);
          System.out.println(helloImpl.sayHello());
          helloImpl.shutdown();
          }

        catch (Exception e) {
          System.out.println("ERROR : " + e) ;
          e.printStackTrace(System.out);
        }
      }
    }

## 「Hello World」의 구축 방법과 실행 방법

「Hello World」프로그램은 단순합니다만, 이 프로그램을 통해,「정적 호출」을 사용하는 CORBA 프로그램의 개발에 필요한 작업 모든 것을 배워, 경험할 수가 있습니다.

이 예에서는 네임 서비스가 필요합니다. 네임 서비스란, 객체 참조에 이름을 바인드 해 CORBA 객체에 명명할 수가 있는 CORBA 서비스입니다. 「네임 바인딩」은 네임 서비스에 포함되어 클라이언트는 이름을 주어 목적의 객체 참조를 취득할 수 있습니다. 이번 버젼의 Java SE 에 동고 되고 있는 네임 서비스에는, 2 개의 옵션이 있습니다. 일시 네이밍 서비스인 `tnameserv` 와 bootstrap 서비스, 일시 네이밍 서비스, 지속 네이밍 서비스, 또는 서버 매니저를 포함한 demon 프로세스인 `orbd` 입니다. 이 예에서는 `orbd` 를 사용합니다.

이 예를 실행하기에 즈음해, Solaris 소프트웨어의 사용시는, 포트 1024 미만으로 프로세스를 개시하는 경우, root 사용자가 될 필요가 있습니다. 이 때문에, 1024 이상의 포트를 사용하는 것을 추천합니다. 이 예에서는,`-ORBInitialPort` 옵션을 사용해 디폴트의 포트 번호를 오버라이드(override) 합니다. 다음의 설명에서는, Java IDL Object Request Broker Daemon (`orbd`)용으로 포트 1050 을 사용할 수 있는 것을 전제로 하고 있습니다. 필요하면 다른 포트로 변경해 주세요. Windows 로 이 예를 실행하는 경우는, 경로명에 backslash (\)를 사용합니다.

개발 머신으로 이 클라이언트서버 어플리케이션을 실행하려면 , 다음과 같이 합니다.

1. 프로그램 파일을 작성하는지,HelloImplBase.zip 를 다운로드해 해동합니다.

2. `Hello.idl` 파일이 놓여져 있는 디렉토리로 이동합니다.

3. IDL 파일로부터 IDL-to-Java 컴파일러 `idlj` 를 실행해, Stub와 스켈리턴을 작성합니다. 이 순서는, java/bin 디렉토리의 패스를, 사용하는 패스에 포함하고 있는 것을 전제로 하고 있습니다.

   주: ImplBase 는 POA 모델이 있으므로 추천 되지 않습니다만, 버젼 1.3 이전의 J2SE 로 기술된 서버와 호환성을 가지기 위해서(때문에) 제공되고 있습니다. 이것은 비표준 모델이므로, 이것을 사용해 새로운 서버를 작성하는 것은 추천하지 않습니다.

         idlj -fall -oldImplBase Hello.idl

   `idlj` 컴파일러의 `-fall` 옵션을 사용해, 클라이언트와 서버측의 바인딩의 양쪽 모두를 생성할 필요가 있습니다. 이 커멘드행으로 디폴트의 서버측 바인딩이 생성됩니다. 이것은 POA 프로그래밍 모델인 것을 전제로 하고 있습니다. `-oldImplBase` 옵션은, 디폴트의 POA 상속 모델 서버측 바인딩은 아니고 ImplBase 상속 모델 서버측 바인딩을 생성하도록, 컴파일러에 지시합니다. `idlj` 옵션의 상세한 것에 대하여는,「IDL-to-Java 컴파일러의 옵션」을 참조해 주세요.

   `idlj` 컴파일러에서는 다수의 파일이 생성됩니다. 실제로 생성되는 파일의 수는, IDL 파일의 컴파일시에 선택된 옵션에 따라서 다릅니다. 생성된 파일에는 표준의 기능이 있으므로, 프로그램을 배치해 실행할 때까지는 무시해도 괜찮습니다. `Hello.idl` 의 `idlj` 컴파일러로, 커멘드행의 `-fall` 옵션을 사용해 생성되는 파일은 다음과 같습니다.

   - `_HelloImplBase.java`

     이 추상 클래스는서버 스켈리턴으로, 서버용으로 기본적인 CORBA 기능을 제공합니다. 이 클래스에서,`InvokeHandler` 와 `Hello` 인터페이스가 구현됩니다. 이것은 `org.omg.CORBA.portable.ObjectImpl` 를 상속합니다. 서버 클래스 `HelloImpl` 는 `_HelloImplBase` 를 상속합니다.

   - `_HelloStub.java`

     이 클래스는「클라이언트 Stub」로, 클라이언트용으로 기본적인 CORBA 기능을 제공합니다. 이것은 `org.omg.CORBA.portable.ObjectImpl` 를 상속해,`Hello` 인터페이스를 구현합니다.

   - `Hello.java`

     이 인터페이스에는 작성한 IDL 인터페이스의 Java 판이 포함됩니다. Hello.java 인터페이스는 표준적인 CORBA 객체 기능을 주는 `org.omg.CORBA.Object` 인터페이스를 상속합니다. 또 `HelloOperations` 인터페이스와 `org.omg.CORBA.portable.IDLEntity` 도 상속합니다.

   - `HelloHelper.java`

     이 클래스는 보조 기능, 특히 CORBA 객체 참조를 적절한 형태에 캐스트 하는 `narrow()` 메소드를 제공합니다. Helper 클래스는 CORBA 스트림에의 데이터형의 입출력과`Any` 의 데이터형의 삽입과 추출을 취급합니다. Holder 클래스는, Helper 클래스의 메소드에 입출력을 위양 합니다.

   - `HelloHolder.java`

     HelloHolder.java 이 `final` 클래스에는,`Hello` 형의 퍼블릭 인스턴스 멤버가 들어옵니다. IDL 형의 파라미터가 `out` 또는 `inout` 이면 Holder 클래스가 사용됩니다. 여기에서는,`org.omg.CORBA.portable.OutputStream` 및 `org.omg.CORBA.portable.InputStream` 인수에 대한 오퍼레이션이 규정됩니다. 이러한 인수는 CORBA 에는 존재합니다만, Java 의 시멘틱스에는 간단하게 매핑 할 수 없습니다. Holder 클래스는 Helper 클래스의 메소드에 입출력을 위양 합니다. Holder 클래스는 `org.omg.CORBA.portable.Streamable` 를 구현합니다.

   - `HelloOperations.java`

     이 인터페이스에는 `sayHello()` 메소드 및 `shutdown()` 메소드가 포함됩니다. IDL-to-Java 매핑은, IDL 인터페이스로 정의된 오퍼레이션을 모두 이 파일에 짜넣어, Stub와 스켈리턴으로 공유합니다.

4. `HelloApp` 디렉토리에 있는 Stub와 스켈리턴도 포함해`. java` 파일을 컴파일 합니다. 이 순서는, java/bin 디렉토리가 실행 패스에 포함되어 있는 것을 전제로 하고 있습니다.

          javac *. java HelloApp/*.java

5. `orbd` 를 기동합니다.

   UNIX 커멘드 쉘로 `orbd` 를 기동하려면 , 다음과 같이 입력합니다.

         orbd -ORBInitialPort 1050 -ORBInitialHost localhost&

   Windows 의 MS-DOS system prompt에서는, 다음과 같이 입력합니다.

         start orbd -ORBInitialPort 1050 -ORBInitialHost localhost

   `1050` 은 네임서버-를 실행하는 포트입니다. `-ORBInitialPort` 는 필요한 커멘드행의 인수입니다. Solaris 소프트웨어의 사용시는, 1024 보다 작은 포트로 프로세스를 개시하는 경우는, root 사용자가 될 필요가 있습니다. 이 때문에, 1024 이상의 포트를 사용하는 것을 추천합니다.

   `-ORBInitialHost` 는, 생략 가능한 커멘드행 인수입니다. 이 예에서는, 클라이언트와 서버는 어느쪽이나 개발 머신으로 실행하고 있으므로, 호스트를 `localhost` 로 설정했습니다. 복수의 머신으로 개발하는 경우는, 호스트명에 옮겨놓습니다. 이 프로그램을 2 대의 머신으로 실행하는 경우의 예는,「2 대의 머신으로 실행하는 Hello World 프로그램」을 참조해 주세요.

6. Hello 서버를 기동합니다.

   UNIX 커멘드 쉘로 Hello 서버를 기동하려면 , 다음과 같이 입력합니다.

         java HelloServer -ORBInitialPort 1050 -ORBInitialHost localhost&

   Windows 의 MS-DOS system prompt에서는, 다음과 같이 입력합니다.

         start java HelloServer -ORBInitialPort 1050 -ORBInitialHost localhost

   이 예의 `-ORBInitialHost localhost` 는 생략 할 수가 있습니다. 네임서버-가 Hello 서버로서 동일 호스트상에서 동작하고 있기 때문입니다. 네임서버-가 다른 호스트로 동작하고 있는 경우는, IDL 네임서버-가 동작하고 있는 호스트를 `-ORBInitialHost` nameserverhost 로 지정합니다.

   전회의 순서와 같게 네임서버- (`orbd`)의 포트를 지정합니다. 예를 들어 `-ORBInitialPort 1050` 과 같이 됩니다.

   서버가 실행중이 되면(자), 다음과 같은 메세지가 단말에 표시됩니다.

       HelloServer ready and waiting ...

7. 클라이언트 어플리케이션을 실행합니다.

         java HelloClient -ORBInitialPort 1050 -ORBInitialHost localhost

   이 예의 `-ORBInitialHost localhost` 는 생략 할 수가 있습니다. 네임서버-가 Hello 클라이언트로서 동일 호스트상에서 동작하고 있기 때문입니다. 네임서버-가 다른 호스트로 동작하고 있는 경우는, IDL 네임서버-가 동작하고 있는 호스트를 `-ORBInitialHost` nameserverhost 로 지정합니다.

   전회의 순서와 같게 네임서버- (`orbd`)의 포트를 지정합니다. 예를 들어 `-ORBInitialPort 1050` 과 같이 됩니다.

   클라이언트가 실행중이 되면(자), 다음과 같은 메세지가 단말에 표시됩니다.

          Obtained a handle on server object: IOR: ...
          Hello World !!
          HelloServer Exiting ...

이 튜토리얼을 종료하면(자), 네임서버- (`orbd`) 지 하든가 종료해 주세요. DOS prompt에서는, 서버를 실행하고 있는 윈도우를 선택해 `Ctrl+C` 라고 입력하면(자) 정지합니다. UNIX 쉘에서는, 프로세스를 검출해 종료 (kill)합니다. 서버를 명시적으로 정지할 때까지는, 호출 대기 상태가 계속됩니다.

「2 대의 머신으로 실행하는 Hello World 프로그램」 에서는, 클라이언트와 서버라고 하는 2 대의 머신으로 간단한 어플리케이션을 분산시키는 방법의 일례를 나타냅니다.

홈

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