Этот документ обсуждает, как записать Java Удаленный Вызов метода (RMI) программы, которые могут получить доступ к удаленным объектам при использовании интернет-Протокола Межшара (IIOP). Заставляя Ваши программы RMI соответствовать маленькому набору ограничений, Ваши клиенты CORBA на любом языке могут получить доступ к серверам IIOP RMI. IIOP RMI дает Вам простоту в употреблении RMI вместе с функциональной совместимостью языка CORBA/IIOP.
Каков IIOP RMI?
RMI
С RMI можно записать распределенные программы в языке программирования Java. RMI удобен, Вы не должны изучить отдельный язык определения интерфейсов (IDL), и Вы получаете свойственную "запись Java однажды, выполняете куда угодно" преимущество. Клиенты, удаленные интерфейсы, и серверы пишутся полностью в Java. RMI использует Java Удаленный Протокол Метода (JRMP) для удаленной передачи объекта Java. Чтобы получить быстрое введение в запись программ RMI, см. Учебную веб-страницу RMI. Тот документ описывает запись простого "Привет Мировая" программа RMI.
RMI испытывает недостаток в функциональной совместимости с другими языками, потому что это не использует CORBA-IIOP в качестве протокола связи.
IIOP, CORBA, и IDL Java
IIOP является протоколом связи CORBA, используя TCP/IP в качестве транспорта. Это определяет стандарт для передачи клиента и сервера. CORBA является стандартом распределенная архитектура объектов, разработанная Группой по управлению объектами (OMG). Интерфейсы к удаленным объектам описываются в независимом от платформы языке определения интерфейсов (IDL). Отображения от IDL до определенных языков программирования реализуются, связывая язык с CORBA/IIOP.
Java (ТМ) 2 Платформы, Standard Edition (J2SE) CORBA/IIOP реализация известны как IDL Java. Наряду с компилятором idlj, IDL Java может использоваться, чтобы определить, реализовать, и получить доступ к объектам CORBA от языка программирования Java.
Веб-страница IDL Java высказывает Вам хорошее, центральное Java мнение программирования CORBA/IIOP. Чтобы получить быстрое введение в запись программ IDL Java, см. Начинание: Привет Мировая веб-страница.
IIOP RMI
Ранее программисты Java должны были выбрать между RMI и CORBA/IIOP (IDL Java) для распределенных решений для программирования. Теперь, придерживаясь нескольких ограничений, серверный объекты RMI могут использовать протокол IIOP и связаться с клиентскими объектами CORBA, записанными на любом языке. Это решение известно как IIOP RMI. IIOP RMI комбинирует простоту использования стиля RMI с межъязыковым взаимодействием CORBA.
Вот основные флаги rmic, которые поддерживают функциональность CORBA/IIOP:
-iiop - Генерирует тупики/связи IIOP. -iiop -poa - Генерирует тупики/связи IIOP, которые работают с Переносимым Объектным Адаптером (POA). -idl - Генерирует IDL.
Следующие опции используются в соединении с опцией -idl.
-noValueMethods - генерация Остановок IDL для методов и конструкторов в пределах IDL valuetype s. -always - регенерация Сил даже когда существующий stubs/ties/idl более нова чем входной класс. Только допустимый, когда -iiop и/или флаги -idl присутствуют. -idlModule <fromJavaPackage<.class>> <toIDLModule> - Определяет отображение пакета IDLEntity. Например: -idlModule foo.bar my::real::idlmod -idlFile <fromJavaPackage<.class>> <toIDLFile> - Определяет отображение файла IDLEntity. Например: -idlFile test.pkg.X TEST16.idl
Для более подробной информации о компиляторе rmic считайте документацию rmic.
Флаг-iiop
Используя rmic с -iiop опция генерирует тупик IIOP и классы связи вместо Java Удаленный Протокол Метода (JRMP) скелетные классы и тупик. Тупиковый класс является локальным прокси для удаленного объекта. Тупиковые классы используются клиентами, чтобы отправить звонки в сервер. Каждый удаленный интерфейс требует тупикового класса, который реализует тот удаленный интерфейс. Ссылка клиента на удаленный объект является фактически ссылкой на тупик. Классы связи используются на серверной стороне, чтобы обработать входящие вызовы, и диспетчеризировать звонки в надлежащий класс реализации. Каждый класс реализации требует класса связи.
Тупиковые классы также сгенерированы для абстрактных интерфейсов. Абстрактный интерфейс является интерфейсом, который не расширяет java.rmi.Remote, но чьи методы весь бросок или java.rmi.RemoteException или суперкласс java.rmi.RemoteException. Интерфейсы, которые не расширяют java.rmi.Remote и не имеют никаких методов, являются также абстрактными интерфейсами.
ВОПРОС: у Меня есть приложение IIOP RMI, которое работало на J2SE 1.3. Когда я генерирую новые тупики и скелеты, используя rmic -iiop -poa <RMI Interface>, он не работает. Почему?
ОТВЕТ: есть 2 различных способа скомпилировать и выполнить программы IIOP RMI, которые упоминаются ниже. Мы не рекомендуем, чтобы Вы объединили их.
Новый для этого выпуска Java SE является опцией -iiop -poa. Используя флаг -iiop с -poa опция изменяет наследование от org.omg.CORBA_2_3.portable.ObjectImpl до org.omg.PortableServer.Servant. Этот тип отображения нестандартен и не определяется Языком Java к Спецификации Отображения Языка IDL OMG.
Модуль PortableServer для Переносимого Объектного Адаптера (POA) определяет собственный тип Servant. В языке программирования Java тип Servant отображается на Java класс org.omg.PortableServer.Servant. Это служит базовым классом для всех реализаций слуги POA и обеспечивает много методов, которые могут быть вызваны прикладным программистом, так же как методами, которые вызываются POA непосредственно и могут быть переопределены пользователем, чтобы управлять аспектами поведения слуги.
Флаг-idl
Используя rmic с -idl опция генерирует IDL OMG для определенных классов и любых классов, на которые ссылаются. Вы хотели бы использовать эту опцию, когда у Вас есть клиент CORBA на другом языке, который хочет говорить с сервером IIOP RMI.
Отметьте: После того, как IDL OMG сгенерирован, используя rmic -idl, используйте сгенерированный IDL с IDL к C++ или другим языковым компилятором, но не с языковым компилятором IDL к Java. "Круглое смещение" не рекомендуется и не должно быть необходимым. Средство генерации IDL предназначается, чтобы использоваться с другими языками, такими как C++. Клиенты Java или серверы могут использовать исходные типы IIOP RMI.
IDL обеспечивает просто декларативный, язык программирования независимые средства для того, чтобы он определил API для объекта. IDL используется в качестве спецификации для методов и данных, которые могут быть записаны в и вызваны с любого языка, который обеспечивает привязку CORBA. Это включает Java и C++ среди других. См. Язык Java к IDL, Отображающему (OMG) документ для полного описания.
Отметьте: сгенерированный IDL может только быть скомпилирован, используя компилятор IDL, который поддерживает CORBA 2.3 расширения IDL.
Флаг-noValueMethods
Опция -noValueMethods, когда использующийся с -idl, гарантирует, что методы и инициализаторы не включаются в valuetype s испускаемый во время Генерации IDL. Они являются дополнительными для valuetype s и иначе опускаются.
Программное обеспечение IIOP RMI включает компилятор IDL к Java. Этот компилятор поддерживает Объекты CORBA функцией Значения, которая требуется для взаимодействия с IIOP RMI. Это пишется в Java, и так может работать на любой платформе. См. Руководство пользователя Компилятора IDL к Java для деталей того, как использовать этот компилятор.
Как Сделать IIOP Использования Программ RMI
Следующие шаги являются общим руководством к преобразованию приложения RMI к IIOP RMI.
Если Вы используете реестр RMI для того, чтобы назвать службы, Вы должны переключиться на CosNaming. В методе createORB() не передавайте свойство org.omg.ORBClass. Вместо этого используйте ORB.init( args, null ). Вы должны сделать следующее:
В обоих Ваших кодах клиента и сервера Вы должны создать InitialContext для JNDI использование следующего кода:
import javax.naming.*;
...
Context ic = new InitialContext();
Измените все использование реестра RMI lookup() и bind(), чтобы использовать lookup() JNDI и bind() вместо этого. Например, вместо Вашего использования сервера RMI:
Если клиент является апплетом, клиентский апплет должен передать this к плагину CosNaming JNDI. Замените вышеупомянутый код следующим:
import java.util.*;
import javax.naming.*;
...
Hashtable env = new Hashtable();
env.put("java.naming.applet", this);
Context ic = new InitialContext(env);
Если Вы не используете реестр RMI для того, чтобы назвать службы, у Вас есть некоторый другой способ загрузить Вашу начальную ссылку удаленного объекта. Например, Ваш серверный код может использовать сериализацию Java, чтобы записать ссылку на объект RMI на ObjectOutputStream и передавать это к Вашему клиентскому коду для того, чтобы десериализовать в тупик RMI.
На серверной стороне используйте вызов PortableRemoteObject.toStub(), чтобы получить тупик, затем использовать writeObject(), чтобы сериализировать этот тупик к ObjectOutputStream. Код, чтобы сделать это смотрит что-то как:
org.omg.CORBA.ORB myORB = org.omg.CORBA.ORB.init(new String[0], null);
Wombat myWombat = new WombatImpl();
javax.rmi.CORBA.Stub myStub = (javax.rmi.CORBA.Stub)PortableRemoteObject.toStub(myWombat);
myStub.connect(myORB);
// myWombat is now connected to myORB. To connect other objects to the
// same ORB, use PortableRemoteObject.connect(nextWombat, myWombat);
FileOutputStream myFile = new FileOutputStream("t.tmp");
ObjectOutputStream myStream = new ObjectOutputStream(myFile);
myStream.writeObject(myStub);
На клиентской стороне используйте readObject(), чтобы десериализовать удаленную ссылку на объект от ObjectInputStream с кодом как:
FileInputStream myFile = new FileInputStream("t.tmp");
ObjectInputStream myStream = new ObjectInputStream(myFile);
Wombat myWombat = (Wombat)myStream.readObject();
org.omg.CORBA.ORB myORB = org.omg.CORBA.ORB.init(new String[0], null);
((javax.rmi.CORBA.Stub)myWombat).connect(myORB);
// myWombat is now connected to myORB. To connect other objects to the
// same ORB, use PortableRemoteObject.connect(nextWombat, myWombat);
Или измените свои удаленные классы реализации, чтобы наследоваться от javax.rmi.PortableRemoteObject, или явно экспортировать объекты реализации после создания, вызывая PortableRemoteObject.exportObject(). Для большего количества обсуждения этой темы считайте Соединяющиеся тупики IIOP в ШАР.
Измените все места в своем коде, где есть бросок Java удаленного интерфейса, чтобы использовать javax.rmi.PortableRemoteObject.narrow().
Не зависьте от Распределенной Сборки "мусора" (DGC) или используйте любой RMI средства DGC. Используйте PortableRemoteObject.unexportObject(), чтобы неэкспортировать объекты, которые больше не находятся в использовании.
Регенерируйте тупики RMI и связи, используя команду rmic с опцией -iiop. Это произведет тупик и свяжет файлы следующими именами:
Этот пример использует номер порта службы имен 1050. Если бы Вы определили различный порт в шаге 7, то Вы должны использовать тот же самый номер порта в провайдере URL здесь. <Имя хоста> в провайдере URL является именем хоста, которое использовалось, чтобы запустить сервер CosNaming в шаге 7.
Если клиент является апплетом, определите следующие свойства в теге апплета:
Этот пример использует номер порта службы имен 1050. Если бы Вы определили различный порт в шаге 7, то Вы должны использовать тот же самый номер порта в провайдере URL здесь. <Имя хоста> в провайдере URL является именем хоста, которое использовалось, чтобы запустить сервер CosNaming в шаге 7.
Когда Ваше приложение использует тупики IIOP, в противоположность тупикам JRMP, Вы должны должным образом соединить тупики IIOP с ШАРОМ прежде, чем вызвать операции на тупики IIOP (это не необходимо с тупиками JRMP). Этот раздел обсуждает дополнительный шаг 'подключения', требуемый для случая тупика IIOP.
Вызов PortableRemoteObject.exportObject() только создает объект связи и кэширует его для будущего использования. У создаваемой связи нет делегата или ШАРА связанными. Это известно как явный вызов.
PortableRemoteObject.exportObject() происходит автоматически, когда экземпляр слуги создается. Это происходит, когда конструктора PortableRemoteObject вызывают как базовый класс. Это известно как неявный вызов.
Позже, когда PortableRemoteObject.toStub() вызывает приложение, он создает соответствующий Тупиковый объект и связывает это с кэшируемым объектом Связи. Но так как Связь не соединяется и не имеет делегата, у недавно создаваемого тупика также нет делегата или ШАРА.
Делегат устанавливается для тупика только, когда приложение вызывает Stub.connect(orb). Таким образом любые операции на тупике, сделанном перед соединением ШАРА, являются составленным сбоем завещания.
Метод connect делает тупик готовым к удаленной передаче, используя указанный объект ШАРА orb. Соединение обычно происходит неявно, когда тупик получается или отправляется как параметр на удаленном вызове метода, но иногда полезно сделать это, выполняя явный вызов (например, после десериализации). Если тупик уже соединяется с orb (то есть, установили делегата для orb), то соединитесь, не предпринимает мер. Если тупик соединяется с некоторым другим ШАРОМ, то RemoteException бросается. Иначе, делегат создается для этого тупика, и ШАР возражают orb.
Для слуг, которые не POA-активируются, Stub.connect(orb) необходим как необходимая установка.
Ограничения, Когда Рабочие Программы RMI По IIOP
Чтобы сделать существующие программы RMI работавшими IIOP, Вы должны наблюдать следующие ограничения.
Удостоверьтесь, что все постоянные определения в удаленных интерфейсах имеют типы примитивов или Строку и оценены во время компиляции.
Не используйте имена Java, которые конфликтуют со скорректированными именами IDL, сгенерированными Java к правилам отображения IDL. См. раздел 28.3.2 из Языка Java к спецификации Отображения IDL для Java к правилам отображения имени IDL.
Не наследуйте то же самое имя метода в удаленный интерфейс не раз от различных основных удаленных интерфейсов.
Будьте осторожны при использовании имен, которые отличаются только в случае, если. Использование имени типа и переменная того типа, имя которого отличается от имени типа только в случае, если поддерживается. Большинство других комбинаций имен, которые отличаются только в случае, если не поддерживаются.
Не зависьте от времени выполнения, совместно используя ссылок на объект, которые будут сохранены точно, передавая ссылки на объект через IIOP. Время выполнения совместно используя других объектов сохраняется правильно.
Не используйте следующие функции RMI:
RMISocketFactory
UnicastRemoteObject
Unreferenced
Распределенная Сборка "мусора" (DGC) интерфейсы
Другие Вещи Следует Знать
Потребность серверов быть Ориентированным на многопотоковое исполнение
Так как удаленный вызов метода на том же самом удаленном объекте может выполниться одновременно, реализация удаленного объекта должна удостовериться, что ее реализация ориентирована на многопотоковое исполнение.
Взаимодействие с Другими ШАРАМИ
IIOP RMI должен взаимодействовать с другими ШАРАМИ, которые поддерживают CORBA 2.3 спецификации. Это не будет взаимодействовать с более старыми ШАРАМИ, потому что они неспособны обработать кодировки IIOP для Объектов Значением. Эта поддержка необходима, чтобы отправить классы значения RMI (включая строки) по IIOP.
ОТМЕТЬТЕ: Хотя это - истина, что ШАРЫ, записанные на различных языках, должны быть в состоянии говорить с друг другом, мы не протестировали функциональную совместимость ШАРА Java с ШАРАМИ другого поставщика.
Когда я использую UnicastRemoteObject по сравнению с PortableRemoteObject?
UnicastRemoteObject должен использоваться в качестве суперкласса для объектной реализации в программировании RMI. PortableRemoteObject должен использоваться в программировании IIOP RMI. Если PortableRemoteObject используется, можно переключить транспортный протокол или на JRMP или на IIOP в течение времени выполнения.
Известные проблемы
JNDI 1.1 не поддерживает java.naming.factory.initial=com.sun.jndi.cosnaming.CNCtxFactory как параметр Апплета. Вместо этого это нужно явно передать как свойство конструктору InitialContext. Эта возможность поддерживается в JNDI 1.2.
Выполняя Службу Именования на Солярис, следует использовать номер порта, больше чем 1024.
На Солярисе можно испытать "из дескрипторов файлов" проблема, запуская приложения IIOP RMI. Это может произойти, если Вы используете слишком много дескрипторов файлов, которые могут произойти, потому что каждый файл JAR в пути к классу использует один дескриптор файла и JDK, 1.1.6 установки добавляют многочисленные файлы JAR к пути к классу. Прежде, чем запустить приложения, установленные предел дескриптора файла к числу, больше чем его значение по умолчанию 64. Например, определите номер ulimit к 90 или выше, следующим образом:
ulimit -n 90
Дополнительное чтение
Вот некоторые сайты, чтобы получить Вас до скорости с этой технологией:
Домашняя страница IIOP RMI содержит ссылки к документации IIOP RMI, примеру кода, спецификациям, новостям, другим связанным веб-сайтам, и больше. Проверьте это!
Учебное руководство IIOP RMI дает постепенный пример для того, чтобы создать и запустить простое приложение IIOP RMI.
Java домашняя страница RMI содержит ссылки к документации RMI, примерам, спецификации, и больше. Удостоверьтесь, что Вы читаете это.
Язык Java к Отображению IDL, ptc/00-01-06 документ является подробной технической спецификацией IIOP RMI. Для дополнительной информации о том, как спецификация реализуется в этой версии Java SE, см. документ соответствия.