Monday, July 14, 2008

Управление зависимостями при разработке UNO-компонентов для OpenOffice.org на Java

Дополнение к предыдущей статье "Создание Java-расширений для OpenOffice.org".

В прошлой статье я показал как создать простое расширение для OpenOffice.org на Java. Простое - потому что оно ничего не делало с интерфейсом пользователя и при его разработке не использовались функции и классы, реализованные в сторонних библиотеках (JAR'ах).

Практически ни одно более-менее серьезное приложение не обходится без использования сторонних библиотек, взять хотябы log4j, без которого не обходится ни один мой рабочий проект.

Следовательно, если вы используете сторонние библиотеки, вам нужно включить их в CLASSPATH для вашего расширения. Если этого не сделать, то при установке расширения возникнет стандартное java.lang.NoClassDefFoundError.

Есть несколько способов указать CLASSPATH для Java-приложений, но для OOo подходит только один - указать зависимости в манифесте JAR'а компонента. По крайней мере, по другому у меня не получилось.

Чтобы построить CLASSPATH, нужно прописать ссылки на все используемые JAR'ы в файле-манифесте. Но используя Maven2 вы можете облегчить себе эту работу, воспользовавшись plugin'ом Maven2 Assembly Plugin.

Этот plugin позволяет "готовить" различные сборки проекта по описанному файлу сборки. Среди преднастроенных дескрипторов сборки есть jar-with-dependencies. Этот дескриптор позволяет для проектов-библиотек (проекты со свойством packaging установленным в jar) сформировать на выходе один JAR, в котором будут упакованы все зависимые JAR'ы, включая классы и другие артефакты текущего проекта. Все помнят, что JAR - это обычный zip-архив? Так вот, сборка jar-with-dependencies распаковывает все зависимости и скомпилированные артефакты проекта во временную папку, а затем эту папку снова упаковывает в один JAR. А это как раз то, что нам нужно.

Чтобы подключить этот plugin в pom.xml в ветку project/build/plugins нужно прописать:

<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies
</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>attached</goal>
</goals>
</execution>
</executions>
</plugin>


Когда я собрал такой JAR и положил его в корень oxt-архива, мое расширение перестало устанавливаться. Процесс установки прерывался сообщением об ошибке: "Cannot determine registration class!".

Я так и не смог толком понять, почему в этом "большом" JAR'е OOo не мог найти мой регистрационный класс. Проблему удалось решить путем разделения "большого" JAR'а на два - в одном был код моего проекта, в другом - код зависимых JAR'ов. Для этого в процесс сборки проекта пришлось вставить ant:

<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<phase>verify</phase>
<configuration>
<tasks>
<mkdir dir="target/oxt/skip_registration" />
<zip
destfile="target/oxt/skip_registration/${artifactId}-${version}-dependencies.jar">
<zipFileSet
src="target/${artifactId}-${version}-jar-with-dependencies.jar"
excludes="org/keyintegrity/ooo/**" />
</zip>
<zip destfile="target/${artifactId}-${version}.oxt">
<fileSet dir="." includes="README*, LICENSE*, NOTICE*" />
<fileSet dir="target" includes="${artifactId}-${version}.jar" />
<fileSet dir="target/oxt" includes="**/*" />
</zip>
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>


Можно заметить, что в oxt-архиве JAR с зависимостями находится в папке skip_registration. OOo знает про эту папку и он не пытается зарегистрировать ее содержимое как компонент OOo.

Осталось добавить ссылку на этот JAR в CLASSPATH моего компонента и все снова заработало:

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.2</version>
<configuration>
<archive>
<manifestEntries>
<RegistrationClassName> org.keyintegrity.ooo.ActivityMonitor
</RegistrationClassName>
<Class-Path>
skip_registration/${artifactId}-${version}-dependencies.jar
</Class-Path>
</manifestEntries>
</archive>
</configuration>
</plugin>

Thursday, July 10, 2008

Учет затрат при помощи мобильного телефона


С прошлого месяца, когда был запущен online-сервис 4 конверта, мы с Настей пользуемся правилом 4 конвертов для планирования и учета ежедневных трат.

В двух словах, при использовании эта система требует ежедневного занесения трат, которые были произведены за день. Я заметил, что спустя две недели в "конвертах" образовались пустые места, потому что были проблемы с интернетом (как сейчас, например, из-за переезда в новую квартиру) или просто потому, что вечером я так и не дошел до компьютера, чтобы вписать цифру...

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

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

Приложение не предъявляет никаких сверх требований к мобильному телефону: главное - это наличие поддержки Java и настроенный интернет (например, GPRS).

Пользователи сервиса могут скачать приложение с сайта проекта (30 Кб).

Сам проект я выложил как Open Source'овый, там же на сайте можно скачать исходники и свободно использовать их для своих нужд.

Если своих силенок на внесение изменений не хватит, можно там же на сайте или здесь в комментариях оставить пожелания, я посмотрю, что можно будет сделать.

Надеюсь это будет кому-то полезным.