Генерация RMI классов и интерфейса, Модификации вызова методов и сборка - Система автоматизированного разделения кода прикладных программ

Возможности Javaparser по генерации классов сводятся лишь к тому, что можно инстанциировать классы, представляющие собой различные виды выражений. Не смотря на то, что в классах есть несколько конструкторов, кроме конструктора по умолчанию, создание объектов некоторых типов выглядит достаточно громоздко из-за наличия в параметрах списков объектов. Для создания подобных объектов приходится создавать минимум один, зачастую несколько списков, содержащих в себе всего по 1 элементу.

На начальном этапе рассматривалась возможность генерации классов по шаблону путем работы со строками, однако несмотря на недостатки Javaparser при создании классов, использование его функциональности значительно упростило процесс генерации классов.

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

Как уже упоминалось ранее, синтаксическое дерево целиком представляет из себя единицу компиляции.

Пусть единица компиляции будет вершиной дерева. На следующем уровне будут 3 узла, представляющие собой импорт классов и пакетов, непосредственно пакет (а точнее, его название) и объявление класса или интерфейса.

Таким образом, изначально создаются 3 пустые единицы компиляции: для интерфейса, для RMI клиента и сервера.

1) Импортируются все пакеты, которые импортированы в классах, содержащих методы для переноса на БД. Дополнительно, необходимо импортировать следующие классы и интерфейсы из пакета Java. rmi: Remote, RemoteException, Registry и LocateRegistry, - Добавляются во все 3 объекта, на сервер также добавляем UnicastRemoteObject.

Дополнительно необходимо импортировать все классы проекта с указанием их пакетов.

    2) В качестве пакета задается "rmicall". Название значения не имеет, главное, чтобы у всех 3х классов он был одинаков. 3) Задается название и модификаторы генерируемого класса или интерфейса. Дальнейшие действия будут разветвлением поддерева класса. Также необходимо задать классы и интерфейсы, от которых пронаследуются генерируемые. Класс-сервер будет наследником интерфейса 4) Объявление полей. Поле присутствует только у класса-клиента, его тип - Registry. К этому полю будет обращение в каждом методе класса, а инициализироваться оно должно только 1 раз - при поиске удаленного соединения. 5) Создание методов соединения на клиенте и на сервере. В указанных методах присутствует установка SecurityManager, Если он не задан, а также инициализация объекта типа Registry, в случае клиента - он ищет соединение, а в случае сервера - создает его, также задается порт, по которому будут связываться части программы. 6) Создание копий переносимых методов и классов-результатов.

Имена методов во всех 3 классах будут совпадать call+имя_переносимого_метода. К параметрам исходного метода добавляется объект класса, в котором содержится метод, также у методов совпадают с исходным выбрасываемые исключения.

Типом возвращаемого значения у всех методов будут пары <объект-источник, возвращаемое значение метода>, более подробно описанные в Главе 2 п.4.

Так как у интерфейса нет тела метода, то в этот момент объект типа "декларация метода" добавляется к списку членов интерфейса.

Тело метода-клиента представляет собой 3 конструкции: объявление объекта-результата, Try...catch блок и возврат результата (return). Удаленный вызов процедуры может выбросить исключение типа RemoteException, поэтому его необходимо окружить соответствующим Try...catch-блоком.

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

Пример: пусть в классе SomeClass для переноса выбран метод со следующей сигнатурой:

Public String[] getAllNames(int start_pos) {тело Метода}

Для данного метода будет сгенерирован класс-результат:

Public class ResgetAllnames{

Public SomeClass source;

Public String[] result;

}

В интерфейсе будет создана следующее объявление метода:

Public ResgetAllnames callgetAllnames(Some class obj, int start_pos) throws RemoteException;

В классе RMI клиента метод будет выглядеть следующим образом:

Public static ResgetAllnames callgetAllnames(SomeClass obj, int start_pos){

Resgetallnames res=null;

Try{

Res=rmivar. callgetAllNames(obj, start_pos);

}catch(RemoteException e){

E. printStackTrace();

}

Return Res;

}

Rmivar - переменная типа RMIinterface и является полем класса-клиента.

На сервере метод будет выглядеть следующим образом:

Public ResgetAllnames callgetAllnames(SomeClass obj, int start_pos) throws RemoteException{

ResgetAllnames res=new ResgetAllnames();

Res. result=obj. getAllnames(start_pos);

Res. source=obj;

Return res;

}

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

Название параметров у исходного метода и сгенерированных совпадают, так как были взяты из объявления самого метода.

В серверный класс также добавляется метод main, содержащий вызов метода на установку соединения.

7) Сгенерированные методы добавляются в класс, класс добавляется в единицу компиляции и затем содержимое каждой единицы компиляции записывается в файл с названием, соответствующим названию класса или интерфейса.

Модификации вызова методов и сборка

Модификации клиентского кода описаны в главе 2 п.6. Перед выполнением модификаций, исходный код копируется в папку, в которой хранится код RMI сервера. Файлы с модифицированным кодом размещаются вместе с классами RMI клиента. Далее генерируется xml-файл для сборки кода в 2 jar-файла, при этом в архиве для серверной части исполняемым указывается сгенерированный класс RMI-сервера. Далее вызывается maven, который по описанной в XML-файле спецификации собирает архивы.

Таким образом, результатом работы системы будут 2 исполняемых jar-файла, один для запуска на сервере приложений, другой - на сервере баз данных. При этом jar на сервере БД должен запускаться первым, так как он создает возможность удаленного подключения.

Похожие статьи




Генерация RMI классов и интерфейса, Модификации вызова методов и сборка - Система автоматизированного разделения кода прикладных программ

Предыдущая | Следующая