Статьи

Учетная запись разработки гибридного приложения Java / Flex

Недавно он заинтересовался идеей написания гибридного приложения Java / Flex. Он написал онлайн просмотрщик PDF с бэкэндом Java. В этом руководстве описаны шаги, которые он предпринял во время разработки приложения. Это его первый корпоративный проект, и поэтому его следует рассматривать не как руководство эксперта в этой области (потому что это не так!), А как отчет о разработке гибридного приложения Java / Flex. Вы можете связаться с ним по адресу mariusz AT idrsolutions DOT com. — Гертьян Виленга, лидер зоны Javalobby.

Как это работает тогда?

Вы можете увидеть это на http://www.jpedal.org/FlexViewer/RC1/Viewer.html .

Используйте его, чтобы найти файл на диске и затем открыть его:

Это только первая версия, чтобы доказать, что я могу заставить ее работать. У меня большие планы на более поздние версии!

Зритель состоит из двух частей. Java-часть, которая обрабатывает весь хардкорный PDF-анализ и рендеринг, а вторая — Flex-интерфейс, который по сути представляет собой Flash GUI, работающий в браузере. Однако с появлением Adobe AIR нет проблем превратить его в настольное приложение.

Итак, как это работает внутри? Пользователь обращается к приложению Flex и выбирает файл, который хочет просмотреть. Затем этот файл загружается на сервер, на котором выполняется Java-часть приложения в форме веб-службы. Затем, используя Java и стороннюю библиотеку PDF, мы декодируем страницу, получаем необходимую информацию о файле и, наконец, генерируем изображение требуемой страницы файла, который мы хотим просмотреть. Затем ссылка на это изображение отправляется обратно во внешний интерфейс, где приложение Flex извлечет файл изображения с сервера и отобразит его пользователю.

Мы должны использовать стороннюю библиотеку PDF просто потому, что ни Flex, ни Java не обеспечивают требуемой функциональности. Есть несколько библиотек на выбор: я собираюсь использовать JPedal, потому что это простой в использовании API и отличные возможности рендеринга. Нам также понадобится веб-сервер для запуска нашего Java-кода, потому что мы собираемся представить его как веб-сервис, поэтому я буду использовать Tomcat.

Какие инструменты мне понадобятся?

Как читать этот урок?

Учебник разделен на две части:

Затем части делятся на разделы, чтобы отразить структуру проекта. Я буду говорить о каждом из разделов, комментируя важные части исходного кода. В конце каждого раздела будет (если применимо) ссылка на файл со всем необходимым кодом в нем. Файлы исходного кода также будут содержать комментарии. Всякий раз, когда я упоминаю о том, что необходимо сделать в NetBeans, я выделяю этот текст синим цветом , тогда как операции, выполняемые в Flex Builder 3, выделяются зеленым цветом . И последнее, но не менее важное: я буду ссылаться на каталог установки tomcat как CATALINA_HOME в этом руководстве, а также в исходном коде.

Java сторона вещей

Как упоминалось ранее, для демонстрации функциональности компонентов, работающих на сервере, мы будем использовать веб-сервис. На следующем шаге я объясню, как настроить проект веб-приложения в NetBeans 6.1. Те из вас, кто знаком с этим аспектом Java EE, могут пропустить следующий раздел.

Создание веб-службы

В этом разделе я объясню, как настроить проект веб-приложения в NetBeans и добавить к нему веб-службу. Чтобы создать новый проект веб-приложения, нажмите: Файл-> Новый проект … появится окно (снимок экрана ниже), на этом этапе убедитесь, что вы выбрали Веб в категориях и Веб-приложение в проектах.


Выбрав правильные параметры, нажмите Далее . На следующем экране введите имя для проекта. В моем случае это JPedal_Server. Кроме того, нет необходимости менять что-либо еще в этом разделе. Нажмите Далее . На новом экране убедитесь, что Tomcat 6.0.16 выбран в качестве сервера, а Java EE 5 в качестве версии Java EE, как показано на снимке экрана ниже.


Сделав правильный выбор, нажмите Готово . Есть еще один экран, через который мы могли бы пройти, но он относится к платформам, доступным для нашего проекта, которые мы не будем использовать. После нажатия кнопки «Готово» вы заметите, что в главном окне среды IDE теперь отображается содержимое файла index.jsp . Следующим шагом является добавление веб-службы в наше приложение. Для этого вам нужно щелкнуть правой кнопкой мыши на главном узле проекта, выбрать New и в следующем меню выбрать Web Service .


После того, как вы щелкнете по значку веб-службы, вы увидите другое диалоговое окно. Здесь просто укажите имя веб-службы , в моем случае PDFImage, и пакет, скажем, org.maz. Далее нажмите Готово . В главном окне откроется новая вкладка, где вы увидите свою веб-службу в режиме конструктора.


Прежде чем мы начнем добавлять реальный код в наш сервис, нам нужно сделать еще одну вещь. Как я уже упоминал ранее, мы собираемся позволить библиотеке Java PDF справляться со всем сложным анализом и рендерингом PDF. Чтобы это сделать, нам нужно добавить банку JPedal в CLASSPATH проекта. В NetBeans это делается путем щелчка правой кнопкой мыши по главному узлу проекта и выбора «Свойства» в меню. После этого нас приветствует другая диалоговая панель, где мы должны выбрать библиотеки из списка категорий и затем нажать кнопку «Добавить JAR / папку». Это позволит нам найти и выбрать нужную банку.


Когда закончите, нажмите ОК .

Использование библиотеки PDF в Сервисе

После добавления JAR-файла JPedal в путь к классам у нас теперь будет доступ к большому количеству классов, которые помогут нам решить любые проблемы, связанные с PDF. Особенно нас интересует класс PdfDecoder . Этот класс позволяет нам (помимо прочего) открывать файл PDF, узнавать, сколько страниц у него есть, или просто получать изображение определенной страницы в документе. Давайте напишем нашу первую операцию нашего веб-сервиса. В моем случае я назову его firstStart, так как это будет первая операция, которая будет выполнена после полной загрузки файла. Для создания операции мы можем использовать мастер, предоставленный IDE (нажмите кнопку «Добавить операцию»), или мы можем просто ввести код вручную, например так:

// pdf handler object
private PdfDecoder pdf = new PdfDecoder();
// other global variables omitted
@WebMethod(operationName = "firstStart")
public String[] firstStart(String s) {
    if(pdf.isOpen()){
       pdf.closePdfFile();
    }
    try {
      pdf.openPdfFile("LOCATION_OF_UPLOADED_PDF");
    } catch (PdfException ex) {
      // report issue
    }
    // code skipped
    numberOfPages = pdf.getPageCount();
    // generate image of the first page, and provide the path (link) to it.
    String path = this.pdfPath(1);
    return new String[]{path,numberOfPages+""};
}

В приведенном выше коде строковым входным параметром является имя файла, выбранного пользователем на гибкой стороне. Инициализировав объект PDF в точке объявления, мы сначала проверяем, не открыли ли уже файл (эту операцию можно вызывать несколько раз в течение сеанса). Если это так, мы закрываем файл, удаляя все ссылки на него и подготавливая объект PDF для следующей операции. Следующим шагом мы открываем файл PDF. Это файл, который будет загружен на сервер со стороны
клиента. Где на сервере он будет размещен, зависит от того, как написан скрипт загрузки (подробнее об этом далее). Мы также можем попросить объект PDF сообщить нам, сколько страниц имеет данный файл. Мы будем использовать это для навигации на гибкой стороне. То, что мы также можем сделать, это вызвать другую операцию из той же службы,какpdfPath (int) . Это создаст для меня изображение первой страницы и вернет путь к нему. Наконец, мы можем вернуть путь и количество страниц, которые наш документ вернул в гибкое приложение.

Здесь я объясню, как мы превращаем страницу PDF-файла в изображение:

@WebMethod(operationName = "pdfPath")
public String pdfPath(@WebParam(name = "parameter") int parameter) {
BufferedImage buff = null;
try {
buff = pdf.getPageAsImage(parameter);
} catch (PdfException ex) {
// log error
}
File f = new File(serverPath + "Img/"+ name + "/" + name + "_" + parameter + ".png");
// code omitted
try {
ImageIO.write(buff, "png", f);
} catch (IOException ex) {
// log error
}
return f.getName();
}

Входной параметр int — это номер страницы, для которой мы хотим создать изображение. Здесь мы снова используем класс PdfDecoder . Короче говоря, JPedal возвращает требуемую страницу в форме объекта BufferedImage . Мы используем java ImageIO, чтобы записать объект buff в файл png и вернуть его имя.

Итак, мы разрешаем пользователям загружать файлы на сервер, а затем мы генерируем изображения (по 1 на страницу) и сохраняем их на нем. Последняя операция, которая нам нужна, — это операция, которая позаботится обо всем, когда мы закончим, cleanUp (String []) .

@WebMethod(operationName = "cleanUp")
public void cleanUp(@WebParam(name = "fileNameList") String[] fileNameList) {
pdf.closePdfFile();
for(int i=0;i<fileNameList.length;i++){
// code to delete all redundant files
}
}

Когда эта операция вызывается из Flex, в качестве входного параметра будет передан массив, содержащий имена загруженных файлов. В соответствии с соглашением, которое я использовал для именования сгенерированных изображений (fileName_pageNumber), я могу убедиться, что все избыточные файлы будут удалены после того, как пользователь закроет приложение. Здесь важно убедиться, что мы закрыли файл PDF (используя объект PDF).

Финальная версия PDFImage.java

Скрипт загрузки на стороне сервера

Итак, все это время мы предполагали, что наш файл PDF уже находится на сервере. Для этого нам понадобится скрипт загрузки на сервер, который сможет обработать запрос, поступающий со стороны клиента. Короче говоря, на стороне Flex мы используем объект URLRequest и передаем ему скрипт загрузки в качестве URL. Связь между Flex и Java затем обрабатывается внутренне, вдали от глаз пользователя. Все, что нам нужно сделать, это решить, как мы хотим обрабатывать поступающую информацию. Все это делается внутри скрипта загрузки. В нашем случае скрипт загрузки примет форму страницы JSP. Щелкните правой кнопкой мыши основной узел проекта и выберите новый, а затем JSP . Дайте ему имя, в моем случае fileUpload, Удалите содержимое шаблона вновь созданной страницы. Код скрипта будет выглядеть примерно так:

<%
// code omitted
List items = upload.parseRequest(request);
Iterator iter = items.iterator();
while (iter.hasNext()) {
FileItem item = (FileItem) iter.next();

//handling a normal form-field
if (!item.isFormField()) {
byte[] data = item.get();
File f = new File("/CATALINA_HOME/webapps/ROOT/Flex/Pdf/"+ item.getName());
FileOutputStream fileOutSt = null;
try{
fileOutSt = new FileOutputStream(f);
fileOutSt.write(data);
} catch (Exception e){
e.printStackTrace();
fileOutSt.close();
}
fileOutSt.close();
}
}
%>

Ключевым элементом здесь является объект «items», который инкапсулирует данные (и операции, которые вы можете над ними выполнять), отправленные со стороны Flex. Важно то , что код сценария выиграл т компиляции так , как это . Причина этого в том, что мы используем классы, которые не включены ни в Java, ни в Tomcat. Банки, содержащие эти классы, можно найти в пакетах « commons-io-1.4-bin » и « commons-fileupload-1.2.1-bin ». Эти jar-файлы должны быть добавлены в classpath проекта веб-приложения, чтобы скомпилировать код сценария загрузки (исходные и javadoc-файлы можно пропустить).

Окончательная версия fileUpload.jsp

crossdomain.xml: для чего он нужен?

Flash Player, среда выполнения для нашего приложения Flex, имеет множество функций безопасности. Один из них касается связи между различными машинами по сети и обмена данными между ними. Короче говоря, crossdomain.xml можно рассматривать как тип списка, который просматривается проигрывателем Flash. Если клиенты « адрес в этом списке , то обмен данными с сервером может иметь место, в противном случае она не может. Из-за характера нашего приложения мы хотим, чтобы каждый мог загружать файлы на наш сервер и использовать веб-сервис. Файл XML, который вы можете найти внизу этого раздела, был отформатирован для этой цели. Важно то, куда мы помещаем файл, он должен находиться в каталоге ROOT в вашем CATALINA_HOME.(см. первое изображение в разделе «Обтекание») .

<cross-domain-policy>
<allow-http-request-headers-from domain="*" headers="*" secure="false" />
<allow-access-from domain="*" secure="false" />
</cross-domain-policy>

Окончательная
версия crossdomain.xml

 

Завершение

Хорошо, предполагая , что мы «ве сделали все правильно , и у нас нет никаких ошибок в коде, приложение должно быть готово к развертыванию. Перед тем , как сделать это, давайте s убедитесь , что все файлы находятся в нужном месте , и что мы имеем структуру каталогов на сервере , который будет в состоянии держать нашу PDF и PNG файлов.

Перейдите в CATALINA_HOME (каталог установки tomcat). По умолчанию в Windows это «C: \ Program Files \ Apache Software Foundation \ Apache Tomcat 6.0.16», в OS X (Leopard) «/ Library / Tomcat», а в Linux его можно найти в «opt / Кот». Затем перейдите в подкаталог webapps и затем ROOT. Здесь создайте каталог с именем Flex и создайте там один с именем Pdf, а другой — Img. Эта структура должна содержаться в каталоге ROOT, так как она должна быть доступна через интернет-браузер. Структура каталогов должна выглядеть так:


Я предполагаю, что вы будете запускать веб-приложение из NetBeans. Щелкните правой кнопкой мыши узел проекта и выберите « Выполнить» . Сервер приложений запустит и развернет наш проект, запустив окно интернет-браузера по умолчанию и страницу с текстом «Hello World!» должен отображаться . Далее мы можем проверить, работает ли сам веб-сервис. Для этого разверните узел Веб-сервисы и выберите наш сервис PDFImage. Щелкните правой кнопкой мыши и выберите «Тестировать веб-сервис». Если это работало правильно , вы должны увидеть другой веб — страница , которую отображается , на этот раз , содержащий таблицу с информацией о веб — служб , вскрытых нашей веб — приложение. (изображение ниже)

 

Финальная версия проекта JPedalServer

Гибкая сторона вещей

Я предполагаю, что большинство из вас знает больше о Java, чем о Flex. Итак, еще раз, я буду немного прагматичен, когда дело доходит до настройки проекта и начала работы. Однако, как только мы окажемся там, я сконцентрируюсь на использовании веб-сервиса, который мы создали ранее, а затем оставлю большую часть представления данных, макета и визуальных материалов для самостоятельного изучения. Есть много учебников там , и я d действительно хотят сохранить эту ниже 15 страниц: P.

Настройка проекта

В Flex Builder щелкните «Файл» -> «Создать» -> «Проект Flex» . Дайте новому проекту имя , в моем случае Viewer.


Оставьте тип приложения как веб-приложение и нажмите « Готово» . Вы увидите новую вкладку , открытую в главном окне. Это все, что нужно сделать. На данный момент приложение ничего не делает, кроме как компилирует и может быть мгновенно развернуто в браузере по умолчанию, нажав белую стрелку на значке зеленого круга . Отсюда мы можем изменить внешний вид нашего приложения в редакторе WYSIWYG, если мы находимся в режиме конструктора (нажмите кнопку « Дизайн» ) или в представлении «Источник» (нажмите кнопку « Источник»).). Любые изменения, сделанные в одном представлении, будут немедленно отражены в другом. Кроме того, благодаря тому, как настроен Flex Builder 3, каждый раз, когда мы сохраняем проект, он также будет компилироваться. С учетом всего этого позволить s добавить некоторые компоненты , которые позволят нам использовать наш веб — сервиса.

The Mock Up Viewer

Чтобы упростить объяснение того, как гибкое приложение работает, а объем кода, размещенного в этом руководстве, будет меньше, мы создадим программу просмотра макетов. Вроде мини версия того, что вы можете найти здесь . Источник полной версии также будет размещен внизу этого раздела. Я думаю, что будет легче объяснить некоторые вещи таким образом. После того, как вы поймете концепции, стоящие за зрителем макета, а затем посмотрите на полную версию, вы сможете понять большинство вещей, которые вы делаете сами. Все, что нам нужно для начала — это панель с держателем изображения и кнопкой для вызова нашего веб-сервиса. ОК, в FB3 (Flex Builder 3) дважды щелкните по вновь созданному Viewer.mxml (если он еще не выбран). Затем нажмите Источник кнопка.


Весь код представления во Flex написан с использованием XML-подобного языка MXML. Синтаксис более или менее одинаков, как и общие понятия. Но приложение Flex также может использовать код ActionScript. Это делается путем вставки раздела <mx: Script> в код mxml. Как в коде ниже:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
    <mx:Panel x="10" y="10" width="486" height="416" layout="absolute">
        <mx:Image id="img" x="10" y="10" width="446" height="326"/>
        <mx:Button x="195.5" y="344" label="Click Me!" click="doStuff()" />
    </mx:Panel>
    <mx:Script>
        <![CDATA[
        import mx.controls.Alert;
        // all action script code goes here
        private function doStuff(): void {
                mx.controls.Alert.show("This is a popup");
        }
        ]]>
    </mx:Script>
</mx:Application>

Глядя на приведенный выше код, мы можем быстро решить несколько вещей. Например, в коде ActionScript мы можем комментировать, как в Java. Мы можем вызвать наш код AS3 (actionscript 3) в коде mxml, как и функцию doStuff () в обработчике нажатия кнопки. Все компоненты, которые мы добавляем в контекст mxml, должны содержаться в теге <mx: Application>, но вне тега <mx: Script>. Хорошо, что у нас здесь должно быть достаточно, чтобы начать.

Использование веб-службы в Flex

Чтобы иметь возможность использовать веб-сервис во Flex, нам нужно использовать компонент <mx: WebService>. Нам также потребуется URL-адрес нашего веб-сервиса. Откуда вы получаете URL? Предполагая, что вы выполнили часть Java, вы можете получить URL из таблицы при тестировании веб-службы в NetBeans. Это должно выглядеть примерно так: ‘http: // localhost: 8084 / JPedalServer / PDFImage? Wsdl’. Хорошо, теперь для некоторого кода:

<mx:WebService id="ws" wsdl="http://localhost:8084/JPedalServer/PDFImage?wsdl"
fault="handleFirstStartFault(event)"
result="handleFirstStartResult(event)"/>
<mx:Script>
    <![CDATA[
    // some code omitted
    private function handleFirstStartFault(event:FaultEvent):void {
           // executed when something goes wrong
          Alert.show(event.fault.faultString);
    }
    private function handleFirstStartResult(event:ResultEvent):void {
           // executed when the web service returns a result
    }
    private function doStuff(): void {
            // call the firstStart method of the web service
           ws.firstStart("test.pdf");
    }
    ]]>
</mx:Script>

Хорошо, мы начнем с некоторых концепций. Компонент <mx: WebService> имеет обработчик результатов и обработчик ошибок. Обработчик результатов выполняется, когда веб-служба завершает работу и возвращает значение. Результат сбоя срабатывает, когда что-то идет не так, сервер недоступен или произошла ошибка в нашем Java-коде на сервере. HandleFirstStartResult (event) получает объект типа ResultEvent, переданный в параметре. Этот объект представляет собой тип оболочки, которая инкапсулирует результат (event.result) операции веб-службы, а также другие аспекты веб-операции, которые нам не интересны в данный момент. Ситуация выглядит аналогично в случае функции handleFristStartFault (event). Основное отличие здесь состоит в том, что у нас есть ошибочный объект вместо результирующего (event.fault).

Чтобы фактически вызвать одну из операций веб-службы, мы должны сначала убедиться, что мы даем нашему компоненту <mx: WebService> идентификатор. В моем случае это «ш». Используя идентификатор, мы можем ссылаться на наш компонент в коде AS3, точно так же, как я делаю это в функции doStuff (), которая назначается слушателем щелчка на нашей кнопке. Здесь важно то, что автозаполнение не будет показывать нам какие-либо операции веб-службы. Нам просто нужно ввести имя операции, которую мы хотим использовать, и передать ей правильные параметры (если есть). Если мы пропустим по буквам имя операции или передадим неверные параметры, сработает обработчик ошибок компонента веб-сервиса. Для простоты я предположил, что на сервере выполняется файл с именем test.pdf, который уже находится в правильном месте, когда выполняется doStuff ().

Так как же вы на самом деле получаете данные из результирующего объекта?

private function handleFirstStartResult(event:ResultEvent):void {
    // executed when the web service returns a result
    var a:ArrayCollection = event.result as ArrayCollection;
    // if return type was say String ten
    // var s:String = event.result as String;
    var imageName:String = ObjectUtil.toString(a.getItemAt(0));
    // get rid of the quote marks
    imageName = imageName.substring(1,imageName.length-1);
    // drop the '.png'
    dir = uploadFileName.substring(0,uploadFileName.length-4);
    img.source = serverPath + "Flex/Img/"+ dir+ "/"+ imageName;
    // here we handle the number of pages
    var numberOfPages:String = ObjectUtil.toString(a.getItemAt(1));
    var lenght:int = numberOfPages.length;
    numberOfPages = numberOfPages.substring(1,lenght-1);
    // maxPages is a global var in the Flex app
    this.maxPages = parseInt(numberOfPages);
}

Если вы помните, что операция веб-службы firstStart (String) возвращает массив из двух элементов. Я решил возвращать значения таким способом для целей этого урока. Глядя на приведенный выше код, мы видим, что для приведения объекта результата к универсальному объекту ArrayCollection мы используем ключевое слово as. Если бы тип был скажем String, мы бы просто использовали event.result в качестве String. Мы можем получить доступ к элементам в объекте ArrayCollection, используя метод getItemAt (int) . Если мы знаем, что конкретный элемент является строкой, мы можем превратить его в один, используя ObjectUtil.toString (Object). Если это число, мы можем использовать parseInt (String) или parseFloat (String), И последнее о коде выше. Вы, наверное, заметили, что я удаляю первый и последний символ строк, которые я получаю от веб-сервиса. Это потому, что когда вы получаете строку со стороны Java, она включает в себя кавычки строки.

Загрузка файлов в Flex

Этот раздел связан с разделом Java о загрузке файлов. Загрузка файлов на сервер в flex требует наличия двух вещей на сервере. Файл crossdomain.xml и скрипт загрузки. Оба этих файла имеют свои собственные разделы в Java-части руководства. На гибкой стороне мы будем использовать объект FileReference . Этот объект имеет два очень важных метода: browse (FileFilter) и upload (URLRequest).

Когда выполняется метод обзора (FileFilter), открывается диалоговое окно выбора системных файлов. Затем пользователь имеет возможность выбрать нужный файл. Метод также может быть вызван без FileFilter в качестве параметра. В этом случае пользователь может выбрать файл любого типа. После того, как выбор сделан, ссылка на выбранный файл создается, и позже может быть передана ссылка.

Перед использованием метода загрузки (URLRequest) нам нужно указать объект URLRequest.

var request:URLRequest = new URLRequest("http://localhost:8084/JPedalServer/fileUpload.jsp");
request.method = URLRequestMethod.POST;

Именно здесь , что мы используем сценарий загрузки мы подготовили ранее. Мы передаем путь к сценарию в конструкторе объекта URLRequest, а затем устанавливаем для свойства метода значение POST, что в основном означает, что данные будут передаваться с объектом URLRequest с помощью метода HTTP POST. Когда все будет готово и ..upload (запрос) будет выполнен, приложение flex сообщит веб-сервис Java. Будет проверен файл crossdomain.xml. Если связь разрешена, данные будут переданы на сервер. Там скрипт загрузки будет перехватывать объект запроса и записывать данные в файловую систему любым способом, каким пользователь его определит.

var fr:FileReference = null;

public function browse():void {
   fr = new FileReference();
   var pdfFileter:FileFilter = new FileFilter("Pdf Files","*.pdf");
   fr.browse([pdfFileter]);
}

private function upload():void {
    var request:URLRequest = new URLRequest("http://localhost:8084/JPedalServer/fileUpload.jsp")
    request.method = URLRequestMethod.POST;
    fr.upload(request);
}
 

Финальная версия макета зрителя

Финальная версия проекта Viewer

Использование автономной версии Tomcat

Некоторые из вас могут захотеть использовать автономную версию сервера Tomcat вместо той, которая поставляется в комплекте с NetBeans. С этим не должно быть проблем, если вы не забудете отредактировать исходные файлы, чтобы они ссылались на порт 8080 (порт Tomcat по умолчанию) вместо 8084 (если используется через NetBeans).

Что дальше?

На этом этапе у вас есть весь код, необходимый для запуска приложения. Программа просмотра макетов использует только некоторые функции веб-службы. Немного больше работы нужно сделать и для представления данных. Вы можете просмотреть источник Flex Viewer, чтобы увидеть, как я сделал поворот изображения, масштабирование и все остальное. Все исходные файлы (Java и Flex) содержат комментарии и, надеюсь, четко объясняют, как все работает. Любые вопросы или предложения приветствуются, не стесняйтесь, напишите мне (mariusz AT idrsolutions DOT com)!