Spec-Zone .ru
спецификации, руководства, описания, API
Содержание документации

Начинающий Используя IIOP RMI:
Пример Используя POA-на-основе модель серверной стороны


Это учебное руководство показывает Вам шаги, чтобы следовать, чтобы создать распределенную версию классики "Привет Мировая" программа, используя Java™ Удаленный Вызов метода (RMI) по интернет-Протоколу Межшара (IIOP). IIOP RMI добавляет CORBA (Общая Архитектура Посредника запросов к объектам) возможность к связи Java ко многим другим языкам программирования и платформам. Включения IIOP RMI распределяли удаленную Группу управления Веб-поддерживающего Java. Компоненты времени выполнения включают ШАР Java для распределенных вычислений, используя передачу IIOP.

IIOP RMI для программистов Java, которые хотят программировать к интерфейсам RMI, но IIOP использования как базовый транспорт. IIOP RMI предоставляет функциональной совместимости другие объекты CORBA, реализованные на различных языках - но только если все удаленные интерфейсы первоначально определяются как Java интерфейсы RMI. Это особенно интересно к Предприятию использования программистов JavaBeans (EJB), так как модель удаленного объекта для EJBs основана на RMI.

Другая опция для того, чтобы создать распределенные приложения является IDL Java™. IDL Java для программистов CORBA, которые хотят программировать в языке программирования Java, основанном на интерфейсах, определенных в Языке определения интерфейсов CORBA (IDL). Это - "обычный бизнес" программирование CORBA, поддерживая Java точно таким же образом как другие языки как C++ или КОБОЛ.


Учебное руководство: Привет Мировое Приложение

Распределенный Привет Мировой пример использует клиентское приложение, чтобы сделать удаленный вызов метода через IIOP к серверу, работая на узле, с которого был загружен клиент. Когда клиент работает, "Привет Мир!" выводится на экран.

Это учебное руководство организуется следующим образом:

  1. Шаги, чтобы записать исходные файлы
  2. Шаги, чтобы скомпилировать файлы класса
  3. Шаги, чтобы запустить Службу Именования, сервер, и клиент

Запишите или Загрузите Исходные файлы

Есть три задачи завершиться в этом разделе:

  1. Определите функции удаленного класса как интерфейс, записанный в языке программирования Java
  2. Запишите класс реализации
  3. Запишите класс сервера
  4. Запишите клиентскую программу, которая использует удаленную службу
Исходные файлы, создаваемые в этом учебном руководстве (и который может быть загружен здесь):

Определите функции удаленного класса как интерфейс, записанный в языке программирования Java

В языке программирования Java удаленный объект является экземпляром класса, который реализует a Remote интерфейс. Ваш удаленный интерфейс объявит каждый из методов, которые требуется вызвать от других машин. У удаленных интерфейсов есть следующие характеристики:

Для этого примера создайте все исходные файлы в том же самом каталоге, например, $HOME/mysrc/RMIHelloPOA. Вот интерфейсное определение для удаленного интерфейса, HelloInterface. Интерфейс содержит только один метод, sayHello:

//HelloInterface.java
import java.rmi.Remote;

public interface HelloInterface extends java.rmi.Remote {
  public void sayHello() throws java.rmi.RemoteException;
}
Поскольку удаленные вызовы метода могут перестать работать совсем другими способами от локальных вызовов метода (из-за связанных с сетью проблем коммуникации и проблем сервера), удаленные методы сообщат о коммуникационных отказах, бросая a java.rmi.RemoteException. Если Вы хотите больше информации об отказе и восстановлении в распределенных системах, можно хотеть считать Примечание по Распределенным вычислениям.

Запишите Класс Реализации

Как минимум, класс реализации удаленного объекта, HelloImpl.java должен:

Объяснение каждого из предыдущих шагов следует за источником для HelloImpl.java:
//HelloImpl.java
import javax.rmi.PortableRemoteObject;

public class HelloImpl extends PortableRemoteObject implements HelloInterface {
  public HelloImpl() throws java.rmi.RemoteException {
    super();     // invoke rmi linking and remote object initialization
  }

  public void sayHello() throws java.rmi.RemoteException {
    System.out.println( "It works!  Hello World!!" );
  }
}

Реализуйте удаленный интерфейс

В языке программирования Java, когда класс объявляет, что это реализует интерфейс, контракт формируется между классом и компилятором. Заключая этот контракт, класс обещает, что это обеспечит тела метода, или определения, для каждых из сигнатур методов, объявленных в том интерфейсе. Интерфейсные методы неявно public и abstract, так, если класс реализации не выполняет свой контракт, это становится по определению abstract класс, и компилятор укажут на этот факт, если класс не был объявлен abstract.

Класс реализации в этом примере HelloImpl. Класс реализации объявляет, какой удаленный интерфейс (ы) он реализует. Вот HelloImpl объявление класса:

  public class HelloImpl extends PortableRemoteObject
    implements HelloInterface{
Как удобство, класс реализации может расширить удаленный класс, который в этом примере является javax.rmi.PortableRemoteObject. Расширяясь PortableRemoteObject, HelloImpl класс может использоваться, чтобы создать удаленный объект, который использует основанный на IIOP транспорт для передачи.

Определите конструктора для удаленного объекта

Конструктор для удаленного класса обеспечивает ту же самую функциональность как конструктор для неудаленного класса: это инициализирует переменные каждого недавно создаваемого экземпляра класса, и возвращает экземпляр класса программы который названный конструктором.

Кроме того, экземпляр удаленного объекта должен будет быть "экспортирован". Экспорт удаленного объекта делает доступным, чтобы принять входящие удаленные запросы метода, прислушиваясь к входящим вызовам к удаленному объекту на анонимном порту. Когда Вы расширяетесь javax.rmi.PortableRemoteObject, Ваш класс будет экспортироваться автоматически после создания.

Поскольку объектный экспорт мог потенциально бросить a java.rmi.RemoteException, следует определить конструктора, который бросает a RemoteException, даже если конструктор не делает ничего иного. Если Вы забываете конструктора, javac произведет следующее сообщение об ошибке:

        HelloImpl.java:3: unreported exception java.rmi.RemoteException; must be
        caught or declared to be thrown. 
        
        public class HelloImpl extends PortableRemoteObject implements HelloInterface{
               ^ 
        1 error
Рассмотреть: класс реализации для удаленного объекта нуждается к: Вот конструктор для HelloImpl класс:
  public HelloImpl() throws java.rmi.RemoteException { 
    super(); 
  }
Отметьте следующее:

java.rmi.RemoteException проверенное исключение, не исключение на этапе выполнения.

Хотя звонок в конструктора суперкласса без параметров, super(), происходит по умолчанию (даже если опущенный), это включается в этот пример, чтобы ясно дать понять факт, что суперкласс будет создан перед классом.

Обеспечьте реализацию для каждого удаленного метода

Класс реализации для удаленного объекта содержит код, который реализует каждый из удаленных методов, определенных в удаленном интерфейсе. Например, вот реализация для sayHello() метод, который возвращает строку "Это, работает! Привет Мир!!" к вызывающей стороне:
  public void sayHello() throws java.rmi.RemoteException {
    System.out.println( "It works!  Hello World!!" );
  }
Параметры, или возвращаемые значения от, удаленные методы могут быть любым типом данных для платформы Java, включая объекты, пока те объекты реализуют интерфейс java.io.Serializable. Большинство базовых классов в java.lang и java.util реализуйте Serializable интерфейс. В RMI:

Запишите Класс Сервера

Класс сервера является классом, у которого есть a main метод, который создает экземпляр реализации удаленного объекта, и связывает тот экземпляр с именем в Службе Именования. Класс, который содержит это main метод мог быть классом реализации непосредственно, или другим классом полностью.

В этом примере, main метод является частью HelloServer.java, который делает следующее:

Объяснение каждого из предыдущих шагов следует за источником для HelloServer.java:
//HelloServer.java
import javax.naming.InitialContext;
import javax.naming.Context;
import javax.rmi.PortableRemoteObject ;
//Please note that internal Sun APIs
//may change in future releases.
import com.sun.corba.se.internal.POA.POAORB;
import org.omg.PortableServer.*;
import java.util.*;
import org.omg.CORBA.*;
import javax.rmi.CORBA.Stub;
import javax.rmi.CORBA.Util;

public class HelloServer {
  public HelloServer(String[] args) {
    try {
      Properties p = System.getProperties();
      // add runtime properties here
      //Please note that the name of the servertool 
      //class may change in future releases.
      p.put("org.omg.CORBA.ORBClass", 
          "com.sun.corba.se.internal.POA.POAORB");
      p.put("org.omg.CORBA.ORBSingletonClass", 
          "com.sun.corba.se.internal.corba.ORBSingleton");

      ORB orb = ORB.init( args, p );

      POA rootPOA = (POA)orb.resolve_initial_references("RootPOA");

      // STEP 1: Create a POA with the appropriate policies
      Policy[] tpolicy = new Policy[3];
      tpolicy[0] = rootPOA.create_lifespan_policy(
        LifespanPolicyValue.TRANSIENT );
      tpolicy[1] = rootPOA.create_request_processing_policy(
        RequestProcessingPolicyValue.USE_ACTIVE_OBJECT_MAP_ONLY );
      tpolicy[2] = rootPOA.create_servant_retention_policy(
        ServantRetentionPolicyValue.RETAIN);
      POA tPOA = rootPOA.create_POA("MyTransientPOA", null, tpolicy);
          
      // STEP 2: Activate the POA Manager, otherwise all calls to the
      // servant hang because, by default, POAManager will be in the 
      // HOLD state.
      tPOA.the_POAManager().activate();

      // STEP 3: Instantiate the Servant and activate the Tie, If the
      // POA policy is USE_ACTIVE_OBJECT_MAP_ONLY
      HelloImpl helloImpl = new HelloImpl();
      _HelloImpl_Tie tie = (_HelloImpl_Tie)Util.getTie( helloImpl );
      String helloId = "hello";
      byte[] id = helloId.getBytes();
      tPOA.activate_object_with_id( id, tie );


      // STEP 4: Publish the object reference using the same object id
      // used to activate the Tie object.
      Context initialNamingContext = new InitialContext();
      initialNamingContext.rebind("HelloService", 
        tPOA.create_reference_with_id(id, 
          tie._all_interfaces(tPOA,id)[0]) );
      System.out.println("Hello Server: Ready...");
      
      // STEP 5: Get ready to accept requests from the client
      orb.run();
    } 
      catch (Exception e) {
        System.out.println("Problem running HelloServer: " + e);
        e.printStackTrace();
      } 
  }


  public static void main(String args[]) {
    new HelloServer( args );
  }
}

Создайте Переносимый Объектный Адаптер (POA) с соответствующими политиками

main метод сервера сначала должен создать Переносимый Объектный Адаптер (POA) с соответствующими политиками. Например:
      Policy[] tpolicy = new Policy[3];
      tpolicy[0] = rootPOA.create_lifespan_policy(
        LifespanPolicyValue.TRANSIENT );
      tpolicy[1] = rootPOA.create_request_processing_policy(
        RequestProcessingPolicyValue.USE_ACTIVE_OBJECT_MAP_ONLY );
      tpolicy[2] = rootPOA.create_servant_retention_policy(
        ServantRetentionPolicyValue.RETAIN);
      POA tPOA = rootPOA.create_POA("MyTransientPOA", null, tpolicy);

Переносимый Объектный Адаптер (POA) разрабатывается, чтобы обеспечить объектный адаптер, который может использоваться с многократными реализациями ШАРА с минимумом необходимой перезаписи, чтобы иметь дело с реализациями различных поставщиков. Поддержка POA была представлена в версии 1.4 J2SE.

POA также предназначается, чтобы позволить персистентные объекты - по крайней мере, с точки зрения клиента. Таким образом, насколько клиент заинтересован, эти объекты всегда живы, и поддерживают значения данных, сохраненные в них, даже при том, что физически, сервер, возможно, был перезапущен много раз, или реализация может быть обеспечена многими различными объектными реализациями.

POA позволяет объектному конструктору намного больше управления. Ранее, реализация объекта была ответственна только за код, который выполняется в ответ на запросы метода. Теперь, дополнительно, конструктор имеет больше контроля над идентификационными данными объекта, состоянием, хранением, и жизненным циклом.

В этом примере значения политики включают:

Для получения дополнительной информации по политикам POA сошлитесь на Главу 11, Переносимый Объектный Адаптер CORBA/IIOP 2.3.1 Спецификации в http://www.omg.org/cgi-bin/doc?formal/99-10-07

Активируйте менеджеров POA

У каждого объекта POA есть связанное POAManager объект. Менеджер POA может быть связан с одним или более объектами POA. Менеджер POA инкапсулирует состояние обработки POAs, с которым оно связывается. В этом шаге активируется менеджер POA. Если этот шаг отсутствует, все звонки Servant завис бы, потому что по умолчанию менеджер POA будет в HOLD состояние.

      tPOA.the_POAManager().activate();

Создайте экземпляр удаленного объекта и активируйте Связь

main метод сервера должен создать экземпляр реализации удаленного объекта, или Слугу. Например:
    HelloImpl helloImpl = new HelloImpl();
Конструктор экспортирует удаленный объект, что означает, что когда-то создаваемый, удаленный объект готов принять входящие вызовы.

При использовании технологии IIOP RMI Ваши реализации используют делегацию (известный как модель Связи), чтобы связать Вашу реализацию с интерфейсом. Когда Вы создаете экземпляр своей реализации, как выше, Вы также должны создать объект Связи связать ее с интерфейсом CORBA. Следующие немного строк кода активируют Связь, но только если политика POA USE_ACTIVE_OBJECT_MAP_ONLY.

      _HelloImpl_Tie tie = (_HelloImpl_Tie)Util.getTie( helloImpl );
      String helloId = "hello";
      byte[] id = helloId.getBytes();
      tPOA.activate_object_with_id( id, tie );

Опубликуйте ссылку на объект, используя тот же самый объектный идентификатор, используемый, чтобы активировать объект Связи

Для вызывающей стороны (клиент, коллега, или клиентское приложение), чтобы быть в состоянии вызвать метод на удаленный объект, та вызывающая сторона должна сначала получить ссылку на удаленный объект.

Как только удаленный объект регистрируется на сервере, вызывающие стороны могут искать объект по имени (использующий службу именования), получить ссылку удаленного объекта, и затем удаленно вызвать методы на объект. В этом примере мы используем Демона Посредника запросов к объектам (orbd), который является процессом демона, содержащим Службу Начальной загрузки, Переходную Службу Именования, Персистентную Службу Именования, и Диспетчер серверов.

Например, следующий код связывает имя "HelloService" со ссылкой для удаленного объекта:

      Context initialNamingContext = new InitialContext();
      initialNamingContext.rebind("HelloService", 
        tPOA.create_reference_with_id(id, 
          tie._all_interfaces(tPOA,id)[0]) );
      System.out.println("Hello Server: Ready...");

Отметьте неотступно следование за параметрами rebind вызов метода:

Подготовьтесь принимать запросы от клиента

Следующая строка кода, когда вызвано основным потоком, позволяет ШАРУ выполнить работу, используя основной поток.
      orb.run();

Запишите клиентскую программу, которая использует удаленную службу

Клиентское приложение в этом примере удаленно вызывает sayHello метод, чтобы получить строку "Привет Мир!" чтобы вывести на экран, когда клиентское приложение работает. Вот код для клиентского приложения:

//HelloClient.java
import java.rmi.RemoteException;
import java.net.MalformedURLException;
import java.rmi.NotBoundException;
import javax.rmi.*;
import java.util.Vector;
import javax.naming.NamingException;
import javax.naming.InitialContext;
import javax.naming.Context;

public class HelloClient {

  public static void  main( String args[] ) {
    Context ic;
    Object objref;
    HelloInterface hi;

    try {
      ic = new InitialContext();
    } catch (NamingException e) {
        System.out.println("failed to obtain context" + e);
        e.printStackTrace();
        return;
    }
        
    // STEP 1: Get the Object reference from the Name Service
    // using JNDI call.
    try {
      objref = ic.lookup("HelloService");
      System.out.println("Client: Obtained a ref. to Hello server.");
    } catch (NamingException e) {
        System.out.println("failed to lookup object reference");
        e.printStackTrace();
        return;
    }

    // STEP 2: Narrow the object reference to the concrete type and
    // invoke the method.
    try {
      hi = (HelloInterface) PortableRemoteObject.narrow(
        objref, HelloInterface.class);
      hi.sayHello();
    } catch (ClassCastException e) {
        System.out.println("narrow failed");
        e.printStackTrace();
        return;
      } catch( Exception e ) {
            System.err.println( "Exception " + e + "Caught" );
            e.printStackTrace( );
            return;
        }
  }
}

Во-первых, клиентское приложение получает ссылку на реализацию удаленного объекта (рекламируемый как "HelloService") от службы имен, используя Интерфейс Именования и Каталога Java [ТМ] (JNDI) вызовы. Как Naming.rebind метод, Naming.lookup метод берет java.lang.String значение, представляющее имя объекта искать. Вы предоставляете Naming.lookup() имя объекта, который Вы хотите искать, и это возвращает объект, связанный с тем именем.


Скомпилируйте Файлы Класса

Исходный код для этого примера теперь полон, и каталог содержит четыре файла: В этом разделе Вы компилируете файл реализации удаленного объекта, HelloImpl.java, чтобы создать .class файлы должны были работать rmic. Вы тогда работаете rmic компилятор, чтобы создать тупики и скелеты. Тупик является прокси клиентской стороны для удаленного объекта, который вперед IIOP RMI призывает к диспетчеру серверной стороны, который поочередно вперед звонок в фактическую реализацию удаленного объекта. Последняя задача состоит в том, чтобы скомпилировать остающееся .java исходные файлы, чтобы создать .class файлы.

Следующие задачи будут завершены в этом разделе:

  1. Скомпилируйте реализацию удаленного объекта
  2. Использовать rmic генерировать тупики и скелеты
  3. Скомпилируйте исходные файлы

Скомпилируйте реализацию удаленного объекта

Создать тупик и скелетные файлы, rmic компилятор должен быть выполнен на полностью определенных именах пакета скомпилированных файлов класса, которые содержат реализации удаленного объекта. В этом примере файл, который содержит реализации удаленного объекта, HelloImpl.java. Чтобы генерировать тупики и скелеты, мы должны сначала скомпилировать HelloImpl.java, следующим образом:

    javac -d . -classpath . HelloImpl.java

"-d ."опция указывает, что сгенерированные файлы должны быть помещены в каталог, из которого Вы выполняете компилятор."-classpath ."опция указывает на это файлы на который HelloImpl.java зависит может быть найден в этом каталоге.

Использовать rmic генерировать скелеты и тупики

Чтобы создать CORBA-совместимый тупик и скелетные файлы, работайте rmic компилятор с -poa -iiop опция. rmic -poa -iiop команда берет одни или более имен классов в качестве параметра и производит файлы класса формы _MyImpl_Tie.class и _MyInterface_Stub.class. Удаленный файл реализации, HelloImpl.class, имя класса, чтобы передать в этом примере.

Для объяснения rmic опции, обратитесь к Операционной среде Соляриса rmic страница руководства или Microsoft Windows rmic страница руководства.

Создать тупик и скелет для HelloImpl реализация удаленного объекта, выполненная rmic как это:

    rmic -poa -iiop HelloImpl

Предыдущая команда создает следующие файлы:

Скомпилируйте исходные файлы

Чтобы скомпилировать исходные файлы, работайте javac команда следующим образом:

    javac -d . -classpath . HelloInterface.java HelloServer.java HelloClient.java

Эта команда создает файлы класса HelloInterface.class, HelloServer.class, и HelloClient.class. Они - удаленный интерфейс, сервер, и клиентское приложение соответственно. Для объяснения javac опции, можно сослаться на Солярис javac страница руководства или Microsoft Windows javac страница руководства.


Запустите Службу Именования, сервер, и клиентское приложение

Следующие задачи будут завершены в этом разделе:
  1. Запустите Службу Именования
  2. Запустите сервер
  3. Выполните клиентское приложение

Запустите Службу Именования

Для этого примера мы будем использовать Демона Посредника запросов к объектам, orbd, который включает и Переходный процесс и Персистентную Службу Именования, и доступен с каждой загрузкой J2SE 1.4 и выше.

Для вызывающей стороны (клиент, коллега, или клиентское приложение), чтобы быть в состоянии вызвать метод на удаленный объект, та вызывающая сторона должна сначала получить ссылку на удаленный объект.

Как только удаленный объект регистрируется на сервере, вызывающие стороны могут искать объект по имени, получить ссылку удаленного объекта, и затем удаленно вызвать методы на объект.

Чтобы запустить Службу Именования, работать orbd из командной строки. Эта команда не производит вывода и обычно выполняется в фоновом режиме. Для больше на orbd инструмент, можно обратиться к orbd страница руководства.

Для этого примера, на операционной системе Соляриса:

    orbd -ORBInitialPort 1060&

или, на операционной системе Microsoft Windows:

    start orbd -ORBInitialPort 1060

Следует определить порт, на котором можно работать orbd. Для этого примера порт 1060 выбирается, потому что в операционной среде Соляриса, пользователь должен стать корнем, чтобы запустить процесс на порту под 1024.

Следует остановить и перезапустить сервер любое время, Вы изменяете удаленный интерфейс или используете измененные/дополнительные удаленные интерфейсы в реализации удаленного объекта. Иначе, тип ссылки на объект, связанной в Службе Именования, не будет соответствовать измененный класс.

Запустите сервер

Откройте другое окно терминала и изменитесь на каталог, содержащий исходные файлы для этого примера. Команда для того, чтобы выполнить клиент была распространена ниже, чтобы облегчить читать, но должна быть введена без возвратов между строками. Следующая команда показывает, как запустить HelloServer сервер. Конечно, если Вы использовали порт кроме 1060 или узел кроме localhost, запускаясь orbd инструмент, замените те значения в команде ниже с фактическими значениями, используемыми, чтобы запустить orbd.

    java 
      -classpath . 
      -Djava.naming.factory.initial=com.sun.jndi.cosnaming.CNCtxFactory
      -Djava.naming.provider.url=iiop://localhost:1060 
      HelloServer 

Для объяснения java опции, можно сослаться на Солярис java страница руководства или Microsoft Windows java страница руководства.

Вывод должен быть похожим на это:

Hello Server: Ready ...

Выполните клиентское приложение

Как только Служба Именования и сервер работают, клиентское приложение может быть выполнено. Из нового окна терминала пойдите в каталог исходного кода, и выполните клиентское приложение из командной строки, как показано ниже. Команда для того, чтобы выполнить клиент была распространена ниже, чтобы облегчить читать, но должна быть введена без возвратов между строками. Конечно, если Вы использовали порт кроме 1060 или узел кроме localhost, запускаясь orbd инструмент, замените те значения в команде ниже с фактическими значениями, используемыми, чтобы запустить orbd.
    java 
      -classpath . 
      -Djava.naming.factory.initial=com.sun.jndi.cosnaming.CNCtxFactory
      -Djava.naming.provider.url=iiop://localhost:1060 
      HelloClient 
После выполнения клиентского приложения Вы будете видеть вывод, подобный следующему в Вашем окне терминала или окне командной строки:
Client: Obtained a ref. to Hello server.

Окно сервера возвратит следующее сообщение:

It works! Hello World!!

Это завершает учебное руководство. Если Вы готовы идти дальше к более сложным приложениям, вот некоторые источники, которые могут помочь:


Oracle и/или его филиалы Авторское право © 1993, 2011, Oracle и/или его филиалы. Все права защищены.
Свяжитесь с Нами

-->