Технология RMI. Java. (Лекция 15)

Содержание

Слайд 2

Технология RMI Как правило, приложения RMI состоят из двух различных программ:

Технология RMI
Как правило, приложения RMI состоят из двух различных программ: сервера

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

Распределённые объектные приложения должны осуществлять следующее: Нахождение удалённых объектов. Приложения могут

Распределённые объектные приложения должны осуществлять следующее:
Нахождение удалённых объектов. Приложения могут

использовать различные механизмы получения ссылок на удалённые объекты.
Например, приложение может зарегистрировать свои удалённые объекты с помощью аппарата простых имён — реестра RMI (RMI registry).
В качестве альтернативы, приложение может передавать и возвращать ссылки на удалённые объекты внутри других удалённых вызовов.
Общение с удалёнными объектами. Детали взаимосвязи между удалёнными объектами управляется RMI.
Для программиста удалённое общение выглядит почти так же, как и вызов обычных методов в Java.
Загрузка определений классов, объекты которых передаются.
Так как RMI позволяет передавать объекты, он
также предоставляет механизмы загрузки определений классов
и передачи информации объектов.
Слайд 4

На рисунке показана структура RMI приложения

На рисунке показана структура RMI приложения

Слайд 5

Сервер вызывает реестр для того, чтобы связать имя с удалённым объектом.

Сервер вызывает реестр для того, чтобы связать имя с удалённым объектом.


Клиент ищет удалённый объект по его имени в реестре сервера и затем вызывает его метод.
Реализация RMI приложения включает следующие шаги:
Определение удалённых интерфейсов.
Удалённый интерфейс определяет методы, которые могут
быть удалённо вызваны клиентом.
Клиент программируется под удалённый
интерфейс, а не под классы-реализации этих
интерфейсов.
Проектирование таких интерфейсов включает
определение типов объектов, которые будут
использоваться в качестве параметров и возвращаемых
значений для этих методов.
Если какие-либо из этих интерфейсов ещё не существуют,
то их тоже нужно определить
Слайд 6

2. Реализация удалённых объектов. Удалённые объекты должны реализовать один или несколько

2. Реализация удалённых объектов.
Удалённые объекты должны реализовать один или несколько удалённых

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

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

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

в любой момент
после того, как определены удалённые
интерфейсы
Рассмотрим пример RMI приложения
Определение удалённых интерфейсов
import java.rmi.*;
public interface AddServerIntf extends Remote{
double add (double d1, double d2) throws
RemoteException;
}
Слайд 8

2. Реализация удалённых объектов. import java.rmi.*; import java.rmi.server.*; /* все удалённые

2. Реализация удалённых объектов.
import java.rmi.*;
import java.rmi.server.*;
/* все удалённые

объекты должны расширять UnicastRemoteObject, который обеспечивает функциональные возможности на удалённых машинах */
public class AddServerImpl extends
UnicastRemoteObject implements AddServerIntf{
public AddServerImpl() throws RemoteException{
// конструктор серверной реализации
}
public double add (double d1, double d2) throws
RemoteException{
return d1+d2; // реализация метода
}
}
Слайд 9

Регистрация RMI объекта в реестре import java.rmi.*; import java.net.*; public class

Регистрация RMI объекта в реестре
import java.rmi.*;
import java.net.*;
public class AddServer{
public static

void main (String[] args){
try{
// создаём экземпляр «обработчика»
AddServerImpl ASI = new AddServerImpl();
// метод rebind обновляет RMI-реестр и
// связывает имя(“Plus”) с объектной ссылкой(ASI)
Naming.rebind(“rmi://localhost:1099/Plus”, ASI);
}catch(Exception e){
e.printStackTrace ();
}
}
}
Слайд 10

3. Реализация клиентов. import java.rmi.*; public class AddClient{ public static void

3. Реализация клиентов.
import java.rmi.*;
public class AddClient{
public static void main (String[]

args){
try{
// получаем ссылку на удалённую реализацию
AddServerIntf plus = (AddServerIntf)Naming.lookup(
“rmi://localhost/Plus”);
// Непосредственно обращение к удалённому
методу:
System.out.println(“The sum is: ” + plus.add(8,9));
}catch(Exception e){
e.printStackTrace ();
}
}
}
Слайд 11

Рассмотрим использование rmi. Компилируем все файлы >javac AddServerIntf.java >javac AddServerImpl.java >javac

Рассмотрим использование rmi.
Компилируем все файлы
>javac AddServerIntf.java
>javac AddServerImpl.java
>javac AddServer.java
>javac AddClient.java
2.Генерируем заглушки и

скелеты, для этого нужно использовать инструмент, называемый компилятором RMI:
>rmic AddServerImp
3. Запускаем rmiregistry(сервер)
>rmiregistry
4. На сервере запускаем
>java AddServer
4. Запуск клиента
>java AddClient
На экране получаем
The sum is: 17
Слайд 12

Enterprise JavaBeans Архитектура технологии EJB Чаще всего системы строятся следующим образом.

Enterprise JavaBeans

Архитектура технологии EJB
Чаще всего системы строятся следующим образом.
Есть

клиентское приложение, которое соединяется с сервером БД и посредством SQL запросов манипулирует данными, отображаемыми в клиентском GUI интерфейсе.
Клиентская часть таких систем обычно сложная и на сервер баз данных возлагается, в основном задача, хранения и поддержки целостности данных.
Иногда базы данных поддерживают хранимые процедуры, что позволяет снизить сетевой трафик между сервером и клиентом.
Такая система имеет вид:
Слайд 13

Слайд 14

Такой подход имеет свои плюсы и минусы. В плюс идет относительно

Такой подход имеет свои плюсы и минусы.
В плюс идет относительно

простая архитектура системы и относительно высокая скорость работы при небольшом количестве клиентских обращений к серверу.
В минус идет то, что такую систему сложно модернизировать, так как изменение в БД влекут за собой изменения в клиентской части и наоборот.
В случае нехватки ресурсов сервера, приходится либо наращивать его вычислительную мощность либо использовать распределенную БД, которая не всегда сможет решить возникшую проблему.
Слайд 15

Существует другой подход построения информационных систем. Система разделяется на три уровня.

Существует другой подход построения информационных систем.
Система разделяется на три уровня.


Каждый уровень имеет свои обязанности и функциональные возможности.
На первом уровне находится клиентское приложение, которое обычно "легкое" и занимается в основном презентационным слоем системы.
Второй уровень отвечает за бизнес логику системы и взаимодействует с презентационным слоем, отвечая на его запросы.
Вторым уровнем называют сервер приложения.
На третьем уровне находится база данных, которая, отвечает за хранения данных и за их целостность.
Такая система имеет вид:
Слайд 16

Слайд 17

Такой подход тоже имеет свои плюсы и минусы. В плюс идет:

Такой подход тоже имеет свои плюсы и минусы.
В плюс идет:
разделение

системы на уровни, позволяющее относительно легко модернизировать систему.
возможность групповой работы над системой, в которой каждый из уровней разрабатывается независимо.
компонентная технология EJB ориентирована на возможность распределения второго уровня, т.е. если сервер приложений не справляется с нагрузкой, то есть возможность без единого изменения кода сервера приложений, разнести его на несколько вычислительных машин.
Компоненты, из которых состоит второй уровень, не будут
чувствовать разницы между работой на одной
вычислительной машине и на нескольких машинах.
Минусом таких систем является их направленность на крупные корпоративные решения.
Слайд 18

Продвигается 5 уровневая архитектура на основе EJB:

Продвигается 5 уровневая архитектура на основе EJB:

Слайд 19

Основное в EJB это сервер приложений. Клиентские приложения будут общаться с

Основное в EJB это сервер приложений.
Клиентские приложения будут общаться с

ним через RMI или CORBA.
Обычно сервер приложений предоставляет EJB компонентам соответствующую среду:
хранит права доступа к компонентам (а точнее логины с паролями по доступу к серверу приложений)
поддерживает RMI и CORBA взаимодействие с ними
предоставляет JNDI сервис (сервис именования EJB компонентов),
является координатором транзакций
предоставляет контейнер, в котором будут храниться EJB компоненты,
предоставляет (не всегда) сервис асинхронных сообщений JMS.
Слайд 20

Сервер приложений имеет вид:

Сервер приложений имеет вид:

Слайд 21

JNDI (Java Naming Directory Interface) - эта служба позволяет клиентскими приложениям

JNDI (Java Naming Directory Interface) - эта служба позволяет клиентскими приложениям

находить на сервере приложений EJB компоненты по их имени.
Другими словами, можно взять множество компьютеров, объединить их в сеть, установить на них сервера приложений.
Но сервис JNDI включить только на одном из них.
И получится, что все компоненты EJB будут доступны на одном дереве имен, а работать на разных серверах приложений.
Transaction Service - сервис транзакций.
Этот сервис предоставляет услуги транзакций, как в обычных реляционных базах данных.
Однако, вместо SQL запросов вызываются методы изменяющие состояния компонентов и как только началась транзакция, то все объекты, с которыми осуществляется работа будут в нее вовлечены.
Слайд 22

Security Service - сервис безопасности. Так как сервер приложений предоставляет удаленный

Security Service - сервис безопасности.
Так как сервер приложений предоставляет

удаленный доступ к EJB компонентам, то этот доступ можно ограничить.
Для этого этот сервис создан.
JMS (Java Message Service) - сервис асинхронных сообщений.
Есть возможность послать сообщение и не ждать подтверждение о получении или ответа.
JMS берет всю ответственность за доставку и хранения очередей сообщений, что значительно разгружает клиентские приложения.
Слайд 23

Контейнер Контейнер предоставляет среду, в которой могут функционировать компоненты EJB. Функции

Контейнер
Контейнер предоставляет среду, в которой могут функционировать компоненты EJB.
Функции контейнера:
Разбор XML-описания

компонента EJB (deployment descriptor) и поддержка конфигурации, описанной в этом XML-файле.
Управление жизненным циклом компонента EJB, т.е. для предоставления услуг компонента прописанных в его интерфейсе и зарегистрированном на JNDI, необходимо создавать, уничтожать и кэшировать реализации (объекты), которые будут отвечать на запросы клиентов.
Разбалансировка нагрузки между реализациями (объектами) обслуживающими компонент EJB и управление пулом таких объектов.
Управление транзакциями в компонентах EJB.
В случае с компонентами, которые работают с СУБД,
управление транзакциями сильно связано с механизмом
синхронизации состояния компонентов с состоянием СУБД.
Управление безопасностью доступа к компонентам. Опционально эта функция может быть отключена и проверку прав доступа к методам компонента придется реализовывать своими руками в самом компоненте.
Слайд 24

Контейнер имеет вид:

Контейнер имеет вид:

Слайд 25

Компонентная модель Компоненты EJB имеют два внешних описания (интерфейса). Через них,

Компонентная модель
Компоненты EJB имеют два внешних описания (интерфейса).
Через них, собственно,

клиент и взаимодействует с компонентом.
Слайд 26

Home-интерфейс является точкой входа в компонент. Другими словами любое начало взаимодействия

Home-интерфейс является точкой входа в компонент.
Другими словами любое начало

взаимодействия с компонентами происходит через Home-интерфейсы.
Клиент обращается к интерфейсу и создает через него экземпляры (объекты), которые обслуживают данный компонент.
А в конце своей работы он их уничтожает.
Remote-интерфейс позволяет взаимодействовать с экземплярами (объектами), которые были созданы через фабрику (Home-интерфейс).
Через Remote-интерфейс пользователь вызывает бизнес-методы компонента, которые естественно придется реализовывать, описывая логику приложения.
Слайд 27

Рассмотрим стандартный сценарий взаимодействия клиента с компонентами EJB.

Рассмотрим стандартный сценарий взаимодействия клиента с компонентами EJB.

Слайд 28

1. Клиент ищет Home-интерфейс нужного ему компонента по его имени через

1. Клиент ищет Home-интерфейс нужного ему компонента по его имени через

сервис имен JNDI (клиенту возвращается в результате поиска Home-интерфейс этого найденного компонента).
2. Клиент, через найденный Home-интерфейс, вызывает функцию создания экземпляра компонента на стороне сервера (клиенту возвращается Remote-интерфейс созданного экземпляра компонента).
2.1. Сервер создает этот экземпляр.
3. Клиент вызывает бизнес-метод на созданном компоненте через его Remote-интерфейс этого компонента.
3.1. Сервер вызывает бизнес-метод на конкретном экземпляре компонента.
Слайд 29

Home-интерфейс Таким образом вся работа с компонентами начинается с обращения к

Home-интерфейс
Таким образом вся работа с компонентами начинается с обращения к Home-интерфейсу.


Каждый тип компонент должен его иметь. Пример Home-интерфейса:
Слайд 30

В этом интерфейсе необходимо определить методы двух типов. Это фабричные методы

В этом интерфейсе необходимо определить методы двух типов.
Это фабричные методы

create и поисковые find.
Фабричные методы позволяют создавать для себя экземпляры компонентов на стороне сервера.
При вызове этого метода можно передать параметры инициализации компонента.
Можно иметь несколько фабричных методов с разным числом параметров.
При вызове фабричного метода возвращается ссылка созданного компонента на стороне сервера.
Получив эту ссылку, можно начать общение с созданным компонентом, т.е. вызывать его бизнес методы.
Слайд 31

Поисковые методы позволяют найти уже созданные компоненты на стороне сервера. Поисковые

Поисковые методы позволяют найти уже созданные компоненты на стороне сервера.
Поисковые методы

применимы только к компонентам, которые называются EntityBean или сущностные бины.
Другими словами, время жизни таких компонентов превышает время работы сервера приложений и, чаще всего, состояние таких компонентов отображается в реляционные базы данных.
Слайд 32

Remote-интерфейс После того, как компонент был создан или найден через его

Remote-интерфейс
После того, как компонент был создан или найден через его Home-интерфейс

и получена ссылка на его Remote-интерфейс, можно приступить к взаимодействию с этим EJB-компонентом.
Все способы взаимодействия с компонентом строго определены в полученном Remote-интерфейсе.
Пример Remote-интерфейса:
Слайд 33

Слайд 34

Стандартом, конечно, являются get/set-методы, считывающие и устанавливающие состояния параметров EJB-компонентов. Можно

Стандартом, конечно, являются get/set-методы, считывающие и устанавливающие состояния параметров EJB-компонентов. Можно

определить любые методы в Remote-интерфейсе.
Реализация компонента
После того как были определены Home и Remote интерфейсы своего компонента, необходимо написать реализации методов определенных в них.
К некоторым методам в реализации добавляется приставка ejb.
Пример реализации имеет вид:
Слайд 35

Слайд 36

ctx - ссылка на объект, которая позволяет компоненту получать служебную информацию

ctx - ссылка на объект, которая позволяет компоненту получать служебную информацию

о пользовательских транзакциях и данные о том какой пользователь работает с компонентом.
ds - ссылка на пул соединений с базой данных.
name, title, description, jndi, port - параметры компонента доступные через методы Remote-интерфейса
serverHome - ссылка на Home-интерфейс компонента Server .
setEntityContext/unsetEntityContext - методы, в которых устанавливается ctx. Вызываются только контейнером.
ejbActivate/ejbPassivate - методы управляющие жизненным циклом компонента. Вызываются только контейнером.
ejbRemove - метод который вызывается перед уничтожением компонента на стороне сервера. Для сущностного бина, например, реализует запрос в базу данных на удаление этого компонента из базы.
getConnection - метод который вызывают для взятия соединения из пула соединений (см. ds). Его определяют больше для удобства и он к спецификации EJB не имеет ни какого отношения.
Слайд 37

ejbCreate - методы которые реализует create методы из Home-интерфейса. Например, для

ejbCreate - методы которые реализует create методы из Home-интерфейса.
Например,

для сущностных бинов в нем
реализуют запрос к базе данных для создания
компонента и в нем устанавливают параметры
компонента.
ejbPostCreate - методы вызываются после ejbCreate.
ejbFind - методы реализуют find методы определенные в Home-интерфейсе и производят поиск компонентов в базе данных.
get/set - методы реализуют get/set методы определенные в Remote-интерфейсе.
toString - определен для совместимости с инфраструктурой JAVA.
К спецификации EJB не имеет ни какого отношения.
Слайд 38

Дерево имен JNDI Каждому компоненту EJB сопоставляется имя, которое публикуется на

Дерево имен JNDI
Каждому компоненту EJB сопоставляется имя, которое публикуется на дереве

имен JNDI.
И клиентское приложение обращается к этой службе зная имя под которым зарегистрирован EJB компонент.
Обратившись к службе имен клиентское приложение получает по имени объектную ссылку.
Так как изначально полагается что компоненты работают в разных адресных пространствах с клиентским приложением, т.е. в разных виртуальных машинах и все их взаимодействие является сетевым, то тогда понятие объектной ссылки стоит обобщить.
Классически объектная ссылка это адрес в памяти, но в случае удаленного взаимодействия это адрес хоста, номер порта, плюс служебная информация и плюс еще к тому что эта объектная ссылка уникальная и ее значение не возможно предсказать.
Слайд 39

Самым первый способ получения объектной ссылки выглядит так: запускается компонент на

Самым первый способ получения объектной ссылки выглядит так: запускается компонент на

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

Схематически это выглядит следующим образом:

Схематически это выглядит следующим образом:

Слайд 41

Сессионные бины Сессионный бин по функциональности очень похож на обычный класс,

Сессионные бины
Сессионный бин по функциональности очень похож на обычный класс, от

которого можно порождать объекты и использовать.
Отличительной чертой является способ создания объекта.
Как уже говорилось выше существуют Home-интерфейс, который является точкой входа в бин.
В нем определяется метод create, через который можно создавать сессионные бины на стороне сервера.
Вообще сессионные бины предназначены быть представителем клиента на стороне сервера или быть его функциональным расширением, другими словами они нужны в течении сессии работы клиента, а потом их уничтожают.
Сессионный бин имеет вид:
Слайд 42

Слайд 43

Сессионные бины бывают двух видов: Stateless and Stateful. Другими словами бины

Сессионные бины бывают двух видов: Stateless and Stateful.
Другими словами бины

могут не помнить свое состояние и помнить.
Сессионный бин не помнящий свое состояние
Бывает ситуации, когда не нужно, что бы бин помнил свое состояния между двумя вызовами методов, т.е. информация в бине не сохраняется с помощью методов set и в последующем не запрашивается методами get.
Слайд 44

Сессионный бин помнящий свое состояние Бывает ситуации, когда необходимо, что бы

Сессионный бин помнящий свое состояние
Бывает ситуации, когда необходимо, что бы бин

помнил свое состояния между двумя вызовами методов, т.е. информация о состоянии запоминается в бине с помощью методов set и в последующем восстанавливается методами get.
Жизненный цикл сессионных бинов.
Рассмотрим жизненный цикл Stateless сессионного бина.
Слайд 45

Слайд 46

Жизненный цикл в Stateful сессионного бина имеет вид:

Жизненный цикл в Stateful сессионного бина имеет вид:

Слайд 47

Идея заложенная в сущностные бины следующая. Необходимо хранить информацию в реляционных

Идея заложенная в сущностные бины следующая.
Необходимо хранить информацию в реляционных

таблицах и обеспечить к ним гибкий доступ используя ООП.
Есть реляционная таблица на нее нужно создать сущностный бин.
Реализация сущностного бина соответствует строчки в базе данных.
Сущностный бин имеет вид:
Слайд 48

Слайд 49

Здесь показан пример бина, который обслуживает таблицу всего с двумя столбцами

Здесь показан пример бина, который обслуживает таблицу всего с двумя столбцами

PK и title.
Также присутствуют поисковые методы ejbFind, которые позволяют выдергивать идентификаторы объектов из базы данных, но не отвечают за загрузку их состояний в память.
Процесс перехода из строчки таблицы в объект называется материализацией, а сохранения объекта в строчку таблицы - дематериализацией.
Механизм взаимодействия с сущностными бинами такой же как с сессионными, за исключением того, что на HOME-интерфейсе появляются Find-методы, которые не создают объекты в базе данных, а находят их в БД.
Архитектура сущностного бина отличается понятием основной ключ Primary Key, который представлен в нашем примере как класс EntityPK.
Этот класс обворачивает основной ключ таблицы, которую обслуживает бин.
Слайд 50

Жизненный цикл сущностных бинов Жизненный цикл (ЖЦ) сущностных бинов похож на сессионный, но несколько сложнее:

Жизненный цикл сущностных бинов
Жизненный цикл (ЖЦ) сущностных бинов похож на сессионный,

но несколько сложнее:
Слайд 51

Рассмотрим пример. Разработаем сеансовый компонент без состояния (Stateless Session Bean), который

Рассмотрим пример.
Разработаем сеансовый компонент без состояния (Stateless Session Bean), который

в ответ на запрос будет возвращать некоторую строку.
Удаленный интерфейс
Сначала определим удаленный интерфейс (Remote Interface) разрабатываемого компонента в файле greetRemote.java.
Все виды удаленных интерфейсов расширяют (extends) интерфейс javax.ejb.EJBObject.
import javax.ejb.*;
import java.rmi.*;
public interface greetRemote extends EJBObject {
public String greetme(String s) throws RemoteException;
}
Здесь присутствует единственный метод greetme() - он возвращает текущее время сервера.
Слайд 52

Домашний интерфейс Теперь определим домашний интерфейс (Home Interface) в файле greetHome.java.

Домашний интерфейс
Теперь определим домашний интерфейс (Home Interface) в файле greetHome.java.
import

javax.ejb.*;
import java.rmi.*;
public interface greetHome extends EJBHome {
public greetRemote create() throws
RemoteException,CreateException;
}
Метод create() отвечает за инициализацию экземпляра разрабатываемого компонента.
При необходимости метод create() может быть перегружен, то есть, определены методы create с возможно другим списком формальных параметров.
Слайд 53

Класс компонента import javax.ejb.*; import java.rmi.*; import javax.naming.*; public class greetBean

Класс компонента
import javax.ejb.*;
import java.rmi.*;
import javax.naming.*;
public class greetBean implements SessionBean {
public

String greetme(String s) throws RemoteException {
return "How are you?......."+s;
}
public void ejbCreate(){}
public void ejbRemove(){}
public void ejbActivate(){}
public void ejbPassivate(){}
public void setSessionContext (SessionContext sc ) {}
}
Слайд 54

Клиентское приложение import java.net.*; import javax.ejb.*; import javax.rmi.*; import java.rmi.*; import

Клиентское приложение
import java.net.*;
import javax.ejb.*;
import javax.rmi.*;
import java.rmi.*;
import javax.naming.*;
import java.util.*;
import java.io.*;
import org.jnp.interfaces.NamingContextFactory;
public class

Main{
public static void main(String[] args){
try{
Properties props=new Properties();
Слайд 55

props.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory"); props.put(Context.PROVIDER_URL, "localhost:1099"); props.put(Context.URL_PKG_PREFIXES, "org.jboss.naming:org.jnp.interfaces"); Context ctx=new InitialContext(props); greetHome home

props.put(Context.INITIAL_CONTEXT_FACTORY,
"org.jnp.interfaces.NamingContextFactory");
props.put(Context.PROVIDER_URL, "localhost:1099");
props.put(Context.URL_PKG_PREFIXES,
"org.jboss.naming:org.jnp.interfaces");
Context ctx=new InitialContext(props);
greetHome

home = (greetHome)ctx.lookup("greetJndi");
greetRemote remote=home.create();
String a="Heloooo";
String s = remote.greetme(a);
System.out.println(s);
} catch(Exception e) {
System.out.println(""+e);
}
}
Слайд 56

Компиляция и развертывание Развернем данное приложение с использованием сервера приложений JBoss

Компиляция и развертывание
Развернем данное приложение с использованием сервера приложений JBoss 3.2.


Прежде всего необходимо создать дескрипторы развертывания ejb-jar.xml и jboss.xml.
Дескриптор jboss.xml необходим для регистрации ejb приложения в службе jndi. Данный файл имеет вид:

"http://www.jboss.org/j2ee/dtd/jboss_3_2.dtd">



greetBean
greetJndi



Слайд 57

Дескриптор ejb-jar.xml описывает само приложение ejb и имеет вид: Enterprise JavaBeans

Дескриптор ejb-jar.xml описывает само приложение ejb и имеет вид:

PUBLIC "-//Sun Microsystems, Inc.//DTD
Enterprise JavaBeans 2.0//EN" "http://java.sun.com/dtd/ejb-
jar_2_0.dtd">



greetBean
greetHome
greetRemote
greetBean
Stateless
Container



Слайд 58

В этом дескрипторе развертывания имеются следующие элементы: - корневой элемент. В

В этом дескрипторе развертывания имеются следующие элементы:
- корневой элемент.
В

нем обязательно должен быть один элемент , а также дополнительные элементы.
- словесное описание.
- этот элемент представляет собой идентификатор, который могут использовать некоторые программы, работающие с дескриптором развертывания (Eclipse, JBuilder, NetBeans).
- содержит объявления всех компонентов, описываемых этим дескриптором развертывания.
- в этом элементе описывается сеансовый компонент (Session Bean).
- имя компонента.
- полное имя класса домашнего интерфейса.
Слайд 59

- полное имя класса удаленного интерфейса. - полное имя класса компонента.

- полное имя класса удаленного интерфейса.
- полное имя класса

компонента. Этот класс реализует прикладные методы компонента.
- тип сеансового компонента. Stateless - без состояния, Stateful - с состоянием.
- определяет, управляет ли сеансовый компонент сам своими транзакциями, или за него это делает контейнер EJB.
Значение Container - управляет контейнер, значение Bean - управляет компонент.
Слайд 60

Теперь рассмотрим непосредственно установку и компиляцию: Скачать архив JBoss 3.2 и

Теперь рассмотрим непосредственно установку и компиляцию:
Скачать архив JBoss 3.2 и развернуть

(установка осуществляется простым копированием), например, в директорию
С:\boss-3.2.8.SP1
Создать директорию, например, mybean на диске C
В директории mybean создать поддиректорию META-INF, в нее скопировать файлы ejb-jar.xml и jboss.xml
Файлы greetHome.java, greetBean.java и greetRemote.java скопировать в каталог mybean.
Слайд 61

4. Скомпилировать файлы greetRemote.java и greetHome.java, greetBean.java: >javac –cp .;c:\jboss-3.2.8.SP1\client\jboss-j2ee.jar *.java

4. Скомпилировать файлы greetRemote.java и greetHome.java, greetBean.java:
>javac –cp .;c:\jboss-3.2.8.SP1\client\jboss-j2ee.jar *.java
5. Создать

jar архив:
>jar cvf greet.jar *.class META-INF\*.xml
6. Скопировать greet.jar в каталог c:\jboss-3.2.8.SP1\server\default\deploy\
7. Запустить JBoss : запустить файл run.bat
в каталоге c:\jboss-3.2.8.SP1\bin\
8. Скомпилировать клиент
>javac –cp .;c:\jboss-3.2.8.SP1\client\jboss-j2ee.jar; c:\jboss-3.2.8.SP1\client\jbossall-client.jar Main.java
9. Запустить клиент
>java –cp .;c:\jboss-3.2.8.SP1\client\jbossall-client.jar Main
Слайд 62

В случае использование JBoss 6 и ejb 3, код бина поменяется.

В случае использование JBoss 6 и ejb 3, код бина поменяется.


Интерфейс бина имеет вид Greet.java
public interface Greet {
public String greetme(String s);
}
Удаленный интерфейс будет иметь вид greetRemote.java:
import javax.ejb.Remote;
@Remote
public interface greetRemote extends Greet { }
Слайд 63

Локальный интерфейс greetHome.java будет иметь вид: import javax.ejb.Local; @Local public interface

Локальный интерфейс greetHome.java будет иметь вид:
import javax.ejb.Local;
@Local
public interface greetHome extends Greet

{ }
Код бина имеет вид:
import javax.ejb.*;
@Stateless
public class greetBean implements greetHome,
greetRemote {
public String greetme(String s) {
return "How are you?......."+s;
}
}
Слайд 64

Файл ejb-jar.xml имеет вид: xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd” version="3.0"> JBoss Stateless

Файл ejb-jar.xml имеет вид:

xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd”

version="3.0">
JBoss Stateless Session Bean Tutorial
JBoss Stateless Session Bean Tutorial


Greet
greetHome
greetRemote
greetBean
Stateless
Container



Слайд 65

Файл jboss.xml: xs:schemaLocation="http://www.jboss.org/j2ee/schema jboss_5_0.xsd" version="5.0"> Greet greetRemote greetHome

Файл jboss.xml:

xs:schemaLocation="http://www.jboss.org/j2ee/schema
jboss_5_0.xsd" version="5.0">


Greet

greetRemote
greetHome



Слайд 66

Клиент будет иметь вид: import javax.ejb.*; import javax.naming.*; import java.util.*; import

Клиент будет иметь вид:
import javax.ejb.*;
import javax.naming.*;
import java.util.*;
import java.io.*;
public class Main{
public

static void main(String[] args){
try{
Properties props=new Properties();
props.put(Context.INITIAL_CONTEXT_FACTORY,
"org.jnp.interfaces.NamingContextFactory");
props.put(Context.PROVIDER_URL, "localhost:1099");
props.put(Context.URL_PKG_PREFIXES,
"org.jboss.naming:org.jnp.interfaces");
Слайд 67

InitialContext ctx=new InitialContext(props); Class clazz = greetRemote.class; Greet home = clazz.cast(ctx.lookup("greetRemote"));

InitialContext ctx=new InitialContext(props);
Class clazz =
greetRemote.class;
Greet

home =
clazz.cast(ctx.lookup("greetRemote"));
String a="Heloooo";
String s = home.greetme(a);
System.out.println(s);
} catch(Exception e){
System.out.println(""+e);
}
}
Слайд 68

JMS JMS является еще одной технологией создания распределенных приложений, основанных на

JMS

JMS является еще одной технологией создания распределенных приложений, основанных на модели

обмена сообщениями.
JMS (Java Messaging System) представляет собой интерфейс к внешним системам, ориентированный на работу через сообщения.
При разработке JMS в качестве основной задачи рассматривалось создание обобщенного Java API для приложений, ориентированных на работу с сообщениями (message-oriented application programming ), и обеспечение независимости от конкретных реализаций соответствующих служб обработки сообщений.
Слайд 69

Модель обмена сообщениями (и JMS ) удобно использовать в том случае,

Модель обмена сообщениями (и JMS ) удобно использовать в том случае,

если распределенное приложение обладает следующими характеристиками:
взаимодействие между компонентами является асинхронным;
информация (сообщение) должна передаваться нескольким или даже всем компонентам системы (семантика передачи от одного ко многим);
передаваемая информация используется многими внешними системами, часть из которых неизвестна на момент проектирования системы или интерфейсы которых подвержены частым изменениям (концепция ESB - Enterprise Service Bus );
обменивающиеся информацией (сообщениями) компоненты выполняются в разное время, что требует наличия посредника для промежуточного хранения переданной информации.
Слайд 70

Архитектура JMS выглядит следующим образом

Архитектура JMS выглядит следующим образом

Слайд 71

прикладные программы Java, использующие JMS, называются клиентами JMS (JMS client );

прикладные программы Java, использующие JMS, называются клиентами JMS (JMS client );
система

обработки сообщений, управляющая маршрутизацией и доставкой сообщений, называется JMS-провайдером (JMS provider);
приложение JMS (JMS application) - это прикладная система, состоящая из нескольких JMS клиентов, и, как правило, одного JMS -провайдера. JMS -клиент, посылающий сообщение, называется поставщиком ( producer ). JMS -клиент, принимающий сообщение, называется потребителем ( consumer ). Один и тот же JMS -клиент может быть одновременно и поставщиком, и потребителем в разных актах взаимодействия;
сообщения ( Messages ) - это объекты, передающиеся и принимающиеся компонентами (клиентами JMS );
средства администрирования ( Administrative tools ) - средства управления ресурсами, использующимися клиентами.
Слайд 72

JMS предоставляет два подхода к передаче сообщений. Первый называется "издание-подписка" (

JMS предоставляет два подхода к передаче сообщений.
Первый называется "издание-подписка" (

publish an subscribe ) Этот подход используется в том случае, если сообщение, отправленное одним клиентом, должно быть получено несколькими.
Слайд 73

Второй подход называется "точка-точка" ( point to point ) и служит

Второй подход называется "точка-точка" ( point to point ) и служит

для реализации обмена сообщениями между двумя компонентами.
Слайд 74

Модель передачи сообщений "точка-точка" предоставляет возможность клиентам JMS посылать и принимать

Модель передачи сообщений "точка-точка" предоставляет возможность клиентам JMS посылать и принимать

сообщения (как синхронно, так и асинхронно) через виртуальные каналы, называемые очередями ( queues ).
Модель основывается на методе опроса, при котором сообщения явно запрашиваются (считываются) клиентом из очереди. Несмотря на то, что чтение из очереди могут осуществлять несколько клиентов, каждое сообщение будет прочитано только единожды - провайдер JMS это гарантирует.
Слайд 75

Модель взаимодействия "издание-подписка" При использовании модели взаимодействия "издание-подписка" один клиент (поставщик)

Модель взаимодействия "издание-подписка"
При использовании модели взаимодействия "издание-подписка" один клиент (поставщик)

может посылать сообщения многим клиентам (потребителям) через виртуальный канал, называемый темой (topic ).
Потребители могут выбрать подписку
(subscribe ) на любую тему.
Все сообщения, направляемые в тему, передаются всем потребителям данной темы.
Каждый потребитель принимает копию каждого сообщения.
Слайд 76

Модель передачи сообщений "издание-подписка", по существу, представляет собой модель сервера, инициирующего

Модель передачи сообщений "издание-подписка", по существу, представляет собой модель сервера, инициирующего

соединение и "проталкивающего" информацию на клиента.
В JMS эта концепция реализуется с помощью специальных "слушателей", регистрируемых в системе.
При возникновении нового события слушатель, закрепленный за данной темой, возбуждается.
Слайд 77

Использование JMS технологии. Любой компонент, использующий JMS, прежде всего должен создать

Использование JMS технологии.
Любой компонент, использующий JMS, прежде всего должен создать соединение

с JMS -провайдером - собственно системой, обеспечивающей всю функциональности управления сообщениями. Последовательность действий изображена на схеме
Слайд 78

Рассмотрим модель взаимодействия “точка-точка” на базе JMS провайдера ActiveMQ. import javax.jms.*;

Рассмотрим модель взаимодействия “точка-точка” на базе JMS провайдера ActiveMQ.
import javax.jms.*;
import

org.apache.activemq.ActiveMQConnection;
import
org.apache.activemq.ActiveMQConnectionFactory;
public class Producer {
//Задаем URL JMS сервера, в данном случае подразумевается, что сервер висит на tcp://localhost:61616
private static String url =
ActiveMQConnection.DEFAULT_BROKER_URL;
//имя очереди сообщений
private static String subject = "TESTQUEUE";
Слайд 79

public static void main(String[] args) throws JMSException { //создаем JMS соединение

public static void main(String[] args) throws
JMSException {
//создаем JMS соединение

с сервером
ConnectionFactory connectionFactory =
new ActiveMQConnectionFactory(url);
Connection connection =
connectionFactory.createConnection();
connection.start();
//Для посылки и приема JMS сообщений необходимо создать сессию. True следует использовать в случае транзакций.
Session session = connection.createSession(false,
Session.AUTO_ACKNOWLEDGE);
Слайд 80

//задаем имя очереди Destination destination = session.createQueue(subject); //Для отправки сообщения используется

//задаем имя очереди
Destination destination =
session.createQueue(subject);
//Для отправки сообщения используется MessageProducer


MessageProducer producer =
session.createProducer(destination);
// Создаем обертку для сообщения
TextMessage message =
session.createTextMessage(“Hello”);
Слайд 81

//отправляем сообшение producer.send(message); //закрываем соединение connection.close(); } } Рассмотрим процедуру получения

//отправляем сообшение
producer.send(message);
//закрываем соединение
connection.close();
}
}
Рассмотрим процедуру получения сообщения
public

class Consumer {
ConnectionFactory connectionFactory = new
ActiveMQConnectionFactory(url);
Connection connection =
connectionFactory.createConnection();
connection.start();
Слайд 82

session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); Destination destination = session.createQueue(subject); //Создаем объект

session session =
connection.createSession(false,
Session.AUTO_ACKNOWLEDGE);
Destination destination =
session.createQueue(subject);
//Создаем объект

MessageConsumer для приема сообщений
MessageConsumer consumer =
session.createConsumer(destination);
//Прием сообщения
Message message = consumer.receive();
Слайд 83

if (message instanceof TextMessage) { TextMessage textMessage = (TextMessage) message; System.out.println(“Received

if (message instanceof TextMessage) {
TextMessage textMessage = (TextMessage)
message;


System.out.println(“Received message “+
textMessage.getText() ); }
connection.close();
} }
Слайд 84

JMS API определяет несколько типов сообщений: BytesMessage предназначен для передачи потока

JMS API определяет несколько типов сообщений:
BytesMessage предназначен для передачи потока байт,

который система никак не интерпретирует;
MapMessage предназначен для передачи множества элементов типа "имя-значение", где имена являются объектами строкового типа, а значения - объектами примитивных типов данных Java ;
ObjectMessage предназначен для передачи сериализуемых объектов;
StreamMessage предназначен для передачи множества элементов примитивных типов данных Java (они могут быть последовательно записаны, а затем прочитаны из тела сообщения этого типа);
TextMessage предназначен для передачи текстовой информации.
Слайд 85

Рассмотрим другой пример использования интерфейса MessageListener. public class Myclass implements MessageListener{

Рассмотрим другой пример использования интерфейса MessageListener.
public class Myclass implements
MessageListener{

public static void main(String[] args) throws
JMSException{
ConnectionFactory connectionFactory=
new ActiveMQConnectionFactory(
"tcp://localhost:61616");
Connection connection =
connectionFactory.createConnection();
connection.start();
Слайд 86

Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); Destination destination = session.createQueue(“Queue1”); MessageConsumer consumer

Session session =
connection.createSession(false,
Session.AUTO_ACKNOWLEDGE);
Destination destination =
session.createQueue(“Queue1”);
MessageConsumer consumer =

session.createConsumer(destination);
//Привязываем слушатель к получателю
Myclass m=new Myclass();
consumer.setMessageListener(m);
}
Слайд 87

//Данный метод вызывается, когда в очереди Queue1 появляется сообщение public void

//Данный метод вызывается, когда в очереди Queue1 появляется сообщение
public void onMessage(Message

message){
String messagerecv;
try{
if (message instanceof TextMessage) {
TextMessage textMessage =
(TextMessage) message;
messagerecv = textMessage.getText();
System.out.println(messagerecv);
} catch(JMSException e) {}
}
}
Слайд 88

Рассмотрим модель взаимодействия "издание-подписка“. Прежде всего рассмотрим класс издателя: public class

Рассмотрим модель взаимодействия "издание-подписка“. Прежде всего рассмотрим класс издателя:
public class Publisher

{
public static void main(String[] args) {
try{
//Данные свойства можно также вынести в отдельный файл jndi.properties
Properties props = new Properties();
props.setProperty(
Context.INITIAL_CONTEXT_FACTORY,
"org.apache.activemq.jndi.ActiveMQInitialContextFactory");
props.setProperty(Context.PROVIDER_URL,
"tcp://localhost:61616");
Context ctx = new InitialContext(props);
Слайд 89

//Создаем соединение с JMS сервером TopicConnectionFactory factory = (TopicConnectionFactory)ctx.lookup( "ConnectionFactory"); TopicConnection

//Создаем соединение с JMS сервером
TopicConnectionFactory factory = (TopicConnectionFactory)ctx.lookup(
"ConnectionFactory");
TopicConnection conn =

factory.createTopicConnection();
conn.start();
//Создаем сессию и тему для подписки
TopicSession session = conn.createTopicSession(false,
TopicSession.AUTO_ACKNOWLEDGE);
Topic mytopic=session.createTopic("MyTopic");
Слайд 90

//Создаем издателя TopicPublisher topicPublisher = session.createPublisher(mytopic); //константа NON_PERSISTENT означает, что сообщения

//Создаем издателя
TopicPublisher topicPublisher =
session.createPublisher(mytopic);
//константа NON_PERSISTENT означает, что сообщения не должны

логироваться
topicPublisher.setDeliveryMode(
DeliveryMode.NON_PERSISTENT);
//Создаем объект TextMessage
TextMessage message =
session.createTextMessage();
message.setText("Hello World");
Слайд 91

//Записываем сообщение в тему topicPublisher.publish(message); session.close(); conn.close(); } catch(NamingException e){ e.printStackTrace();

//Записываем сообщение в тему
topicPublisher.publish(message);
session.close();
conn.close();
} catch(NamingException e){
e.printStackTrace();
} catch(JMSException e){
e.printStackTrace();
}

}
Слайд 92

Рассмотрим класс подписчика import javax.jms.*; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException;

Рассмотрим класс подписчика
import javax.jms.*;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import java.util.Properties;
public class Subscriber implements


MessageListener,ExceptionListener {
public static void main(String[] args) throws
JMSException,NamingException{
Слайд 93

//свойства можно вынести в файл jndi.properties, путь к файлу следует указать

//свойства можно вынести в файл jndi.properties, путь к файлу следует указать

в переменной окружения CLASSPATH
Properties props = new Properties();
props.setProperty(
Context.INITIAL_CONTEXT_FACTORY,
"org.apache.activemq.jndi.
ActiveMQInitialContextFactory");
props.setProperty(Context.PROVIDER_URL,
"tcp://localhost:61616");
props.setProperty("topic.MyTopic","MyTopic");
Context ctx = new InitialContext(props);
Слайд 94

//Создаем объект - слушатель Subscriber asyncSubscriber = new Subscriber(); //Создаем соединение

//Создаем объект - слушатель
Subscriber asyncSubscriber =
new Subscriber();
//Создаем соединение
TopicConnectionFactory factory

= (TopicConnectionFactory)ctx.lookup(
"ConnectionFactory");
TopicConnection conn =
factory.createTopicConnection();
//Добавляем обработчика исключений
conn.setExceptionListener(asyncSubscriber);
conn.start();
Слайд 95

//Ищем тему “MyTopic” Topic mytopic = (Topic)ctx.lookup("MyTopic"); //Создаем сессию TopicSession session

//Ищем тему “MyTopic”
Topic mytopic = (Topic)ctx.lookup("MyTopic");
//Создаем сессию
TopicSession session =
conn.createTopicSession(false,
TopicSession.AUTO_ACKNOWLEDGE);
//Создаем подписчика

и добавляем слушателя
TopicSubscriber topicSubscriber =
session.createSubscriber(mytopic);
topicSubscriber.setMessageListener(
asyncSubscriber);
}
Слайд 96

//Метод вызывается при появлении сообщения в теме. public void onMessage(Message message){

//Метод вызывается при появлении сообщения в теме.
public void onMessage(Message message){
TextMessage

msg = (TextMessage)message;
try {
System.out.println("received: " +
msg.getText());
} catch (JMSException ex) {
ex.printStackTrace();
}
}