Caché + Java + Flex, или как мы делали систему управления учебным планированием

    В этой серии статей мы постараемся подробно рассмотреть основные аспекты использования данной связки. Мы применили этот комбайн для реализации одной из подзадач проекта по разработке интеллектуальной системы автоматизированного управления учебным планированием. Для лучшего понимания, стоит сказать несколько слов о самом проекте.

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

    По задумке, к каждому участнику процесса формирования учебного плана (например заведующему кафедры) привязывается агент, являющийся помощником и консультантом. В качестве инструмента, позволяющего легко реализовать таких агентов и обработать их поведение, была выбрана платформа JADE (Java Agent Development Framework).

    В качестве СУБД, была использована Caché компании InterSystems. СУБД была выбрана нами по нескольким причинам. Во-первых, данная СУБД поддерживает объектный подход доступа к данным, что значительно облегчает работу (не считая еще и того, что она позволяет создавать проекции классов на различных языках, но об этом будет рассказано ниже). Во-вторых, в этой системе легко настроить области доступа для пользователей, что пригодится в дальнейшем. Ну и наконец, компания InterSystems всячески поддерживает разработчиков, которые пользуются их продуктами, а также предоставляет лицензии для ВУЗов бесплатно.

    Было принято решение сделать систему кроссплатформенной, для удобства и мобильности в дальнейшем использовании. Для реализации web-интерфейса системы, была выбрана flex-технология (расширяющая базовые возможности flash).
    В итоге, на первом этапе разработки был выделен ряд задач, о которых в дальнейшем и пойдет речь (собственно эти задачи мы и рассмотрим в данной серии статей):
    • разработка модели классов Cache
    • реализация взаимосвязи между Cache и Java
    • разработка web-интерфейса
    • реализация взаимосвязи Java с web-интерфейсом

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

    Кроме описанного выше, на клиенте устанавливается связующий агент, обеспечивающий постоянную связь с агентом JADE и информирующий пользователя о происходящих событиях и сообщениях, передаваемых основным агентом.
    В первой части мы сфокусируем наше внимание на взаимодействии Cache -Java.
    Рассмотрим фрагмент структуры БД Caché, используемый для функционирования агента заведующего кафедрой в мультиагентной системе управления учебным планированием (МАС УУП). Хранимые классы были спроектированы и реализованы в студии Caché.

    Фрагмент базы данных Caché для агента заведующего кафедрой состоит из шести хранимых классов, основным из которых является класс дисциплин (cDiscipline), включающий все необходимые характеристики дисциплины для составления учебного плана. Из приведенной выше диаграммы видно, что дисциплины разделяются по циклам и семестрам, которые, в свою очередь, входят вместе с дисциплинами в состав учебного плана по определённому направлению. Дисциплина может являться базовой и иметь в своём составе несколько других дисциплин, что реализовано отношением Parent. Связь дисциплины с классом cControlForm определяет форму контроля по дисциплине (экзамен или зачёт). Также учебный план содержит список внесенных в него изменений (класс cLogs).
    Для последующей реализации связки хранимых классов Caché с логикой приложения на java, с помощью стандартного механизма проецирования, были сгенерированы классы java-проекций. Ниже представлен код создания java-проекции в классе Caché.
    Projection PrjName As %Projection.Java(ROOTDIR = "c:\Out\");
    //PrjName – имя проекции, ROOTDIR – путь вывода класса на java
    

    Как было отмечено, организация связи с базой данных Caché выполнена с использованием механизма java-проекций, а также библиотек, поставляемых с Caché для связи через JDBC.
    Для облегчения разработки на данном этапе был создан слой m-классов, позволяющий отвязаться от классов java-проекций (c-классов).

    Зачем это сделано? Классы java-проекций для описываемой системы, генерируемые Caché, представлены на данной диаграмме в виде пакета классов «Java c-classes». В пакете «Java m-classes» содержаться классы, каждый из которых соответствует классу из пакета «Java c-classes». Java m- классы повторяют только свойства классов из пакета c-, и помимо этого содержат свои get() и set() методы. Такой подход удобен при постоянных изменениях в классах Caché, поскольку после малейшего изменения в Caché, достаточно заново сгенерировать Java-проекцию необходимого класса Caché и затем произвести замену (а изменять m-классы значительно проще, чем редактировать вновь созданную проекцию). Кроме того этот подход на данном этапе помогает с организацией микротранзакций. К примеру, позволяет легко откатить изменения в m- классах, которые еще не были сохранены в c- (в частности необходимо для алгоритма). А если учесть еще и то, что Java напрямую не поддерживает клонирование, такие микротранзакции значительно облегчают работу. Помимо этого, Granite DS для создания ActionScript проекций требует внесения в основной класс некоторых изменений (об этом будет рассказано во второй части статьи), а внести такие изменения в m- класс легче, чем переписывать частично структуру c- класса. Поэтому такой подход значительно облегчает работу на основном этапе разработки, в то время как, на этапе оптимизации это решение может быть переработано.

    Так, к примеру, с точки зрения эффективности и памяти этот подход выглядит не очень привлекательно. И в дальнейшем от него, скорее всего, придется отходить за счет реализации в с- классах интерфейса Serializable, который необходим для работы Granite DS.
    Класс CacheTransform является связующим звеном между базой данных Caché и java классами. В этом классе реализуется два пути работы с БД Caché: через JDBC и через java-проекции. Для обеспечения связи с БД через JDBC в классе CacheTransform реализована функция подключения к базе данных. Реализация этой функции использует объект класса Database, поставляемого в библиотеке cachedb. Ниже приведён код функции подключения к БД.
    public Boolean InitCon(String port, String user, String pass)
    {
        try {
            username=user;
            password=pass;
            url="jdbc:Cache://localhost:"+port+"/IKIT";
            dbconnection = CacheDatabase.getDatabase(url, username, password);
            connect=true;
            try{
                setParams(port,user,pass);
            }catch (IOException er){System.out.println("[Error of IO]: "+er);}
            return true;
        } catch (CacheException e) {
            e.printStackTrace();
            return false;
        }
    }
    

    Функция InitCon принимает основные параметры подключения (port – номер порта, user – имя пользователя, pass – пароль для подключения к Caché), заносит их в соответствующие глобальные переменные и пытается подключиться к базе данных. При успешном подключении текущие параметры заносятся в конфигурационный файл функцией setParams(port,user,pass). Также, стоит отметить, что url использует localhost, поскольку само java-приложение и БД расположены на одной машине и в дальнейшем стоит унифицировать эту функцию, чтобы она принимала как адрес машины, на которой работает БД, так и область БД (в данном примере область — IKIT).
    Далее рассмотрим порядок считывания данных из БД Caché. В классе CacheTransform для каждого класса java-проекции реализована пара функций, одна из которых загружает один объект класса по Id, а другая все объекты класса. Ниже приведён
    пример кода для загрузки объектов класса cControlForm.
    ///Функция загрузки одного объекта формы контроля
    public mControlForm ReadOneCont(Integer ind)
    {
      try {
           if(connect == true)
           {
            cControlForm temp = (cControlForm) cControlForm._open(dbconnection, new Id(ind));
            return TranformCF(temp);
           }
            return null;
      }
      catch (CacheException e) {
         e.printStackTrace();
         return null;
      }
    }
    
    ///Функция загрузки всех объектов форм контроля
      public void ReadAllCont()
      {
          try {
              if(connect == true)
              {
                  ListOfCF.clear();
                  Iterator k = dbconnection.openByQuery("SELECT  
                  IKIT.cControlForm.%ID FROM IKIT.cControlForm");
                  while (k.hasNext())
                  {
                      ListOfCF.add(TranformCF((cControlForm)k.next()));
                  }
              }
          }
          catch (CacheException e) {
              e.printStackTrace();
          }
      }
    


    Из примера видно, что для загрузки одного объекта по Id используется функция _open класса java-проекции, а для загрузки всех объектов вызывается функция openByQuery объекта dbconnection класса Database, в которую передаётся SQL запрос. Стоит отметить, что IKIT.cControlForm.%ID возвращает коллекцию объектов. Далее в обеих функциях вызывается метод TranformCF:
    ///Трансформация Формы контроля
        public mControlForm TranformCF(cControlForm cur)
        {
            try{
            mControlForm res=new mControlForm();
            res.setId(Integer.parseInt(cur.getId().toString()));
            if(cur.getZET()!=null) res.setZet(cur.getZET().floatValue());
            res.setName(cur.getName());
            return res;
            }
            catch (CacheException e) {
                e.printStackTrace();
             return null;
            }
        }
    

    Как видно из описания, данный метод принимает объект c- класса и в случае успешного преобразования возвращает объект m- класса. В частности данный метод работает c классом ControlForm.
    Порядок сохранения данных в БД Caché аналогичен процессу загрузки и реализован также в классе CacheTransform. Ниже приведён пример для сохранения данных класса cControlForm.
    исходный код cControlForm
    ///Трансформация Формы контроля
    public cControlForm RevTranformCF(mControlForm cur, Integer act)
    {
        try {
            cControlForm res = null;
            if (act == 1)
            {
                System.out.println("//MAS: TRY EDIT CF: "+ act.toString() + "\nID:" + cur.getId().toString());
                res = (cControlForm) cControlForm._open(dbconnection, new Id(cur.getId()));
            }
            else {
                System.out.println("//MAS: TRY ADD CF");
                res = new cControlForm(dbconnection);
       }
            res.setName(cur.getName());
            if(cur.getZet() != null) res.setZET(cur.getZet().doubleValue());
            res._save();
            return res;
        }
        catch (CacheException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
            return null;
        }
    }
    


    В примере входной аргумент act функции RevTranformCF принимает значение 1 или 0. Когда act равен единице, из базы данных загружается объект класса cControlForm, в противном случае, создаётся новый объект класса cControlForm. Далее выполняется присвоение значений атрибутам объекта cControlForm и вызывается функция сохранения.
    Вызов методов объекта класса CacheTransform выполняется в классе UserService, который реализует интерфейс IUserService, используемый в свою очередь классами ActionScript web-приложения. Подробнее о данной связке будет рассказано в следующей части статьи.

    Подводя итоги данной части статьи, можно сказать, что в нашем случае работа с Java-проекциями Cache значительно облегчила работу, поскольку она позволяет обойти связку «Cache класс»-«Данные»-«Java класс», поручая основную работу с данными СУБД. Проекции удобнее и с точки зрения ООП, так как происходит непосредственная работа с классами и отпадает необходимость в создании вручную структуры java-классов для обработки данных. Так, к примеру, вместо SQL запросов, зачастую возвращающих данные, тип которых необходимо знать заранее, используются методы get(), set(), позволяющие получить типизированные данные. Помимо всего прочего, регенерация классов-проекций при компиляции класса Cache избавляет от необходимости вносить значительные изменения в Java-классы, что наблюдалось бы при использовании связи через JDBC.

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

    В следующей части статьи мы расскажем об общей структуре проекта, реализующего связи Caché -Java — Flex, механизмах взаимодействия, а также используемых для этого инструментах. Работу самой системы можно посмотреть здесь.
    InterSystems
    87,00
    Вендор: СУБД Caché, OLAP DeepSee, шина Ensemble
    Поделиться публикацией

    Похожие публикации

    Комментарии 14

      +2
      Как-то плохо сходится
      Было принято решение сделать систему кроссплатформенной, для удобства и мобильности в дальнейшем использовании.

      и
      Поэтому, для реализации web-интерфейса системы, была выбрана flex-технология
        0
        Опечатка, поправил.
        +2
        Не увидел ни одной причины использовать выбранные Вами технологии. Вот честно, такой стек ради задачи где MySQL + PHP за глаза. Попахивает дипломной работой)))
          0
          Вы может быть правы, судя по прыгающему стилю оформления кода — человек мало работал в комманде.
            +1
            В основу архитектуры положена платформа JADE, т.к. одним из основных требований было создание мультиагентной системы. На данном этапе это плохо прослеживается и в статье не очень заметно, но в дальнейшем на это будет сделан серьёзный упор. Поэтому MySQL+PHP к решению такой задачи не подходят совсем.
              0
              Чем вызвано собственно требование использования JADE?
              Интересует, это практическая необходимость или нечто другое?
                0
                В данной статье освещена только часть проекта, касающаяся рассмотренной комбинации Caché + Java + Flex. Сам проект направлен на создание мультиагентной системы управления учебным планированием, в которой каждому пользователю будет предоставлен его собственный агент, через который он и будет взаимодействовать с другими агентами системы. К использованию мультиагентного подхода нас подтолкнула сложность задачи согласования всех учебных планов института и интеграции их друг с другом, в результате чего должны появляться общие лекционные потоки. Мы рассматривали и другой вариант — постановка и решение задачи глобальной оптимизации. Такая задача может быть решена при наличии всех данных, но на данном этапе у нас их нет, да и решение задачи глобальной оптимизации не всегда бывает оптимальным, а внашем случае только количество измерений (искомых параметров) более 20 и достаточно много нетривиальных ограничений.
                Использование мультиагентного подхода позволит решить такую задачу итерационным способом, когда агенты заведующих кафедрами будут взаимодействовать друг с другом, и поэтапно согласовывать учебные планы. В выбранной нами платформе (JADE) реализованы основные механизмы управления жизненным циклом агентов и их взаимодействием. Поэтому мы и используем JADE.
                  0
                  С какими сложностями столкнулись, насколько такой подход ускоряет/замедляет разработку?
                  Реквестирую статью по реализации системы агентов :)
                    0
                    Основной сложностью считаем проектирование архитектуры, которая позволяет разработать мультиагентную систему в web не нарушая самой концепции мультиагентного подхода. Здесь стоит отметить, что сама платформа JADE соответствует специальному стандарту для мультиагентных систем: FIPA. Соединение теории в реализации прикладной системы — это и есть основная сложность. Также стоит отметить сложность подбора и соединения разных технологий разработки ПО для создания этой системы.
                    Что касается ускорения или замедления разработки, ответить сложно, т.к. здесь было бы правильно сравнивать с другими подходами разработки именно мультиагентных систем, которые кроме прочего функцианируют в web. Но здесь существует масса платформ или готовых специализированных мультиагентных систем, но ничего неизвестно о технологиях их разработки.
            0
            Эх, надо что бы кто-то основательно вам поревьюил код, а потом по-хорошему всю систему нужно переписать.

              0
              Для реализации web-интерфейса системы, была выбрана flex-технология (расширяющая базовые возможности flash).

              Думаю, что на сегодняшний день это плохая идея.
              1) Даже Adobe, владелец технологии, делает шаги в сторону HTML5, правда пока только в области мобильных платформ.
              2) Разработка клиентской части медленнее, чем на HTML/CSS/JS, так как требуется перекомпиляция после внесения изменений.
              3) Привязка к поставщику(Vendor lock-in), то есть к Adobe: только от него можно получить SDK и среду разработки Flash Builder, альтернативы среды выполнения(flash plugin), тоже пока сильно уступают «Flash Plugin» от Adobe.

              Adobe Flash повторяет судьбу апплетов Java.
                0
                Приложение на флеше не зависит от браузеров, а только от флэшплеера.
                Разработка на HTML5 ещё не гарантирует преимуществ перед flex, т.к. находится в стадии становления.
                  0
                  Если вы будете загружать swf из главного клиентского приложения, то не обязательно перекомпилировать все. Но Ваша идя мне понравилась, потому что давно мечтаю о as3-интерпретаторе.
                  0
                  Приложение на флеше не зависит от браузеров, а только от флэшплеера.
                  Разработка на HTML5 ещё не гарантирует преимуществ перед flex, т.к. находится в стадии становления.

                  Сейчас браузерные войны закончились и проблем с кросс-браузерной совместимостью стало гораздо меньше, чем раньше.
                  Уход с Flash в HTML/CSS/JS является тенденцией, ее нужно только увидеть.

                  Например, сайт поддержки компании Oracle, был выполнен на Flash. Пользоваться им было, мягко говоря, нудобно. Хотя поначалу впечатлял визуально. Некоторое время назад компания анонсировала, что появилсь и HTML-версия, которую можно выбрать при входе, но она еще не настолько функциональна, как Flash. Затем сообщение, что обе версии равны по функционалу. И вот совсем недавно, что Flash-версия будет отключена и дальнейшая работа будет в HTML-версии.

                  Сильными козырями Flash были, и еще наверно остаются, потоковое аудио/видео.
                  Но ведь вам этого не надо? Уже где-то показывали VoIP-звонилку на HTML5, youtube уже на HTML5.

                  «Цветут бурным цветом» различные JS-библиотеки, облегчающие создание визуальных компонентов и предложений в этой сфере станет еще больше.

                  Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                  Самое читаемое