В первой части статьи мы рассмотрели комбинацию Caché + Java. Здесь будет показана структура проекта непосредственно реализующего комбинацию Caché + Java + Flex, а также основные инструменты и их настройки, используемые для её реализации. Стоит отметить, что здесь будет приведен лишь общий вид взаимодействия, в то время как, конкретные примеры будут рассмотрены в заключительной части. Начнем с описания модулей, входящих в состав проекта, и постепенно перейдем к особенностям их взаимодействия.
Структура проекта
Проект состоит из трёх основных модулей:
- flex – здесь располагаются mxml-классы, описывающие структуру web-интерфейса, дополнительные библиотеки на ActionScript, а также сгенерированные ActionScript-проекции java-классов;
- biz-logic – включает java -c и -m классы (подробнее о данных классах было рассказано в первой части статьи), класс контроллер, а так же классы-интерфейсы, отвечающие за логику приложения;
- web-application – генерируемый модуль, хранящий сформированные jar-файлы из модуля biz-logic и swf из модуля flex. Кроме этого, данный модуль отвечает за генерацию WAR (Web application ARchive), который позже размещается на web-сервере.
Далее стоит сказать несколько слов о применяемых инструментах. В качестве web-сервера был использован Apache Tomcat версии 6.0.35. Как было отмечено в первой части, в качестве основного инструмента для связи Java и ActionScript используется фреймворк Granite DS, представляющий комплексное решение для разработки и интеграции flex + javaEE RIA приложений. Его необходимо подключать как в настройках для flex, так и biz-logic модулей (как это сделать, будет рассказано дальше). Для автоматизации сборки проекта выбран Maven – универсальный инструмент для сборки Java проектов (компиляции, создания jar, создания дистрибутива программы, генерации документации). Maven, по умолчанию, создает по отдельному POM (Project Object Model) файлу для каждого из модулей, а также один общий для всего проекта. POM файлы используются для настройки конфигурации, а также для подключения библиотек из репозиториев (подробнее о работе с Maven можно прочитать здесь, а также работа с Maven подробно рассматривалась на Хабре). Приведем примеры некоторых настроек, использованных нами.
Содержание POM-файлов
Рассмотрим подробнее особенности POM-файлов для каждого из модулей проекта. В POM-файл модуля flex прописываются настройки Granite DS и пути к java-классам, проекции которых необходимо создать. Кроме этого здесь же привязываются используемые библиотеки. К примеру,
<execution>
<goals>
<goal>generate</goal> <!—цель генерация-->
</goals>
<configuration>
<generatorToUse>graniteds21</generatorToUse> <!—используемый генератор-->
<baseOutputDirectory>${project.build.directory}/generated- sources</baseOutputDirectory> <!—выходная директория для проекций-->
<outputDirectory>${project.build.directory}/../src/main/flex </outputDirectory> <!—выходная директория для классов наследующих от проекций-->
<extraOptions>
<tide>true</tide>
<uid>uid</uid>
<entityFactory>org.granite.generator.as3.BVEntityFactory </entityFactory>
<outputEnumToBaseOutputDirectory>false </outputEnumToBaseOutputDirectory>
</extraOptions>
<includeJavaClasses>
<include>edu.samples.sample.domain.**</include> <!—путь к классам, проекции которых необходимо сгенерировать-->
<include>edu.samples.sample.services.I*Service</include> <!—путь к интерфейсам, проекции которых необходимо сгенерировать -->
</includeJavaClasses>
</configuration>
</execution>
Следующий код так же располагается в POM-файле модуля flex и демонстрирует подключение библиотек Granite из репозитория:
<dependency>
<!—основные координаты библиотеки-->
<groupId>org.graniteds</groupId>
<artifactId>granite-core</artifactId>
<!—версия файла библиотеки-->
<version>${graniteds.version}</version>
</dependency>
В POM-файле для модуля biz-logic указываются параметры для генерации jar-файлов.
Кроме этого, необходимо подключить библиотеки cachedb и cachejdbc для работы с Caché (данные библиотеки в виде jar-файлов предоставляются вместе с продуктами Ensemble и Caché. По умолчанию располагаются в “…devjavalibJDK16”).
<dependency> <!—зависимости (библиотеки) используемые для сборки-->
<groupId>cache.cachedb</groupId><!—основные координаты библиотеки-->
<artifactId>cachedb</artifactId>
<type>jar</type> <!—тип файла библиотеке-->
<version>${cachedb.version}</version> <!—версия файла библиотеки-->
<scope>system</scope> <!—назначение библиотеки-->
<systemPath>C:/soft/javalibs/cachedb.jar</systemPath> <!—путь к файлу-библиотеке-->
</dependency>
<dependency>
<groupId>cache.cachejdbc</groupId>
<artifactId>cachejdbc</artifactId>
<version>${cachejdbc.version}</version>
<type>jar</type>
<scope>system</scope>
<systemPath>C:/soft/javalibs/cachejdbc.jar</systemPath>
</dependency>
В POM-файле для модуля web-application прописываются привязка сгенерированных ранее в модуле biz-logic jar-файлов и опции для генерации WAR-файла такие как: output-директория для сгенерированного файла, подключение библиотек war-компилятора (maven-compiler-plugin, maven-war-plugin, maven-dependency-plugin). Так же должны быть прописаны опции для генерации swf-файла.
<plugin>
<!—основные координаты плагина в репозитории-->
<groupId>org.sonatype.flexmojos</groupId>
<artifactId>flexmojos-maven-plugin</artifactId>
<version>${flexmojos.version}</version>
<configuration>
<stripVersion>true</stripVersion>
</configuration>
<executions>
<execution>
<goals>
<goal>copy-flex-resources</goal> <!—цель копирование флекс ресурсов-->
</goals>
<configuration>
<artifactItems>
<artifactItem>
<!—основные координаты файлов для копирования в swf-->
<groupId>edu.sample</groupId>
<artifactId>flex</artifactId>
<type>swf</type> <!—тип генерируемого файла swf-->
<overWrite>true</overWrite> <!—перезаписать существующий-->
<destFileName>sample.swf</destFileName><!— имя сгенерированного файла-->
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
Порядок сборки проекта следующий: компилируются java-классы из модуля biz-logic, затем на их основе с помощью GraniteDS генерируются ActionScript-проекции, которые помещаются в модуль flex. После этого компилируется модуль flex и с помощью плагина org.sonatype.flexmojos (предоставляется Flex) генерируется .swf файл. Он вместе с используемыми библиотеками помещается на сервер по прописанному в конфигурационном файле пути. На основе сгенерированных .swf и .jar файлов, а также используемых библиотек формируется .war файл.
<properties> <!—опции для генерации-->
<war.name>sample</war.name><!—имя сгенерированного war-файла-->
<catalina.home>C:Program FilesApache Software FoundationTomcat
6.0</catalina.home> <!--путь к серверу, на котором будет размещен war-->
<skipTests>true</skipTests>
</properties>
<build>
<finalName>sample</finalName>
<testSourceDirectory>src/test/java</testSourceDirectory>
<plugins>
<!--подключение плагина для компиляции-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<sourсe>1.6</sourсe>
<target>1.6</target>
</configuration>
</plugin>
<!—подключения плагина для генерации war-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<warName>${war.name}</warName>
</configuration>
</plugin>
<!—подключение плагина определяющего зависимости-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.1</version>
<executions>
<execution>
<id>copy</id>
<phase>install</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>edu.sample</groupId>
<artifactId>web-application</artifactId>
<version>1.0</version>
<type>war</type>
<overWrite>true</overWrite>
<destFileName>${war.name}.war</destFileName>
<outputDirectory>${catalina.home}webapps
</outputDirectory>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
После того, как все настройки выполнены, можно приступать к непосредственному рассмотрению механизма взаимодействия Flex + Java + Caché.
Общий вид механизма взаимодействия Flex + Java + Caché
Начнём с того, что всё взаимодействие Flex + Java проходит через ActionScript-проекции, среди которых, кроме проекций хранимых классов (Java-m классы), есть и классы-проекции интерфейсов сервера, отвечающие за логику приложения. В момент запуска web-приложения в браузере (на стороне клиента) при инициализации создается объект, реализующий интерфейс сервисов сервера (в нашем случае это объект userService). Через него и будет в дальнейшем происходить связка flex + java. Для выполнения какой-либо операции над хранимыми объектами вызывается соответствующий метод в userService. В случае удачного прохождения определенных условий на сервере изменения также будут выполнены в БД Caché.
Кроме того, для реализации описанной связки через Granite DS необходимо, чтобы выполнялись следующие условия.
- Класс должен реализовывать интерфейс Serializable.
- В проецируемых классах должен использоваться специальный синтаксис Granite DS. Например, для методов get() и set() проецируемых свойств нужно использовать теги @ExternalizedProperty, а для самого проецируемого класса – @ExternalizedBean, как показано в примере ниже.
@ExternalizedBean(type=DefaultExternalizer.class)
public class mCicl implements Serializable {
…
@ExternalizedProperty
public List<mDiscipline> getListOfDisc() {
return listOfDisc;
}
public void setListOfDisc(List<mDiscipline> listOfDisc) {
this.listOfDisc = listOfDisc;
}
…
}
Не стоит также забывать о java-нотации. Так, к примеру, при именовании свойства с заглавной буквы в проекции, данное свойство будет иметь модификатор доступа private без get и set методов.
Как уже говорилось выше, в модуле flex используется интерфейс (@RemoteDestination) сервисов (@Serviсe) сервера, поэтому в модуле biz-logic должна быть соответствующая реализация данного интерфейса. Например, для проецируемого класса-интерфейса
@RemoteDestination
public interface IUserService {
…
void delOneDisc(Integer i);
…
}
должна быть прописана реализация
@Service
public class UserService implements IUserService {
…
@Override
public void delOneDisc(Integer i) {
objT.deleteOneDisc(i);
}
…
}
Подводя итоги данной части, можно сказать, что здесь мы описали лишь общий механизм взаимодействия Cache + Java + Flex через интерфейсы и проекции, а также необходимые для них настройки, не заостряя внимания на конкретных примерах. Поэтому в следующей части статьи мы уделим больше внимания конкретным практическим примерам. В частности рассмотрим преобразования коллекций на протяжении всей связки, а также примеры передачи объектов от БД до браузера и обратно.
Автор: yakuninyy