Статьи

Значок в системном трее для мониторинга Hudson с Eclipse RCP

Нашей команде понадобился значок в системном трее, который указывает на статус последней сборки в Гудзоне . Я решил написать небольшое приложение с Eclipse RCP, которое заняло у меня около дня.

[Img_assist | NID = 419 | название = | убывание = | ссылка = нет | ALIGN = правая | ширина = 185 | высота = 60]

Почему Eclipse RCP? Во-первых, я не хотел связываться с .NET. У меня только самые тонкие знания .NET, и я не хотел терять время из-за недостатка опыта. Во-вторых, у некоторых из нас есть Mac 🙂

В-третьих, значки в системном трее могут быть добавлены из JVM. Java 6 поддерживает его, как и Eclipse Europa (3.3). Я провел быстрый опрос в нашей команде, и большинство из них хотели избежать установки Java 6 на свои машины. И у некоторых из нас есть Mac 🙂

Так что я закончил создавать свое первое приложение с Eclipse RCP. Для начала я получил последнюю версию Eclipse и следовал инструкциям по созданию нового проекта RCP здесь . Затем я скопировал код, связанный с системным треем, который нашел здесь .

Это заставило меня начать. Первым делом я получил несколько интересных значков, указывающих на успех и неудачную сборку. Я нашел их здесь .

Разработка плагинов (Eclipse рассматривает приложение RCP как своего рода плагин) в Eclipse очень интуитивно понятна, графический интерфейс Eclipse делает все достаточно просто, как запуск приложения из Eclipse. Очевидно, что отладка приложения также очень проста.

Основываясь на сгенерированных классах, я добавил всю свою логику в ApplicationWorkbenchWindowAdvisor класс. Первое раздражение, с которым я столкнулся — это модель потоков Eclipse. У Хадсона есть RSS-лента, которая содержит информацию о состоянии последней сборки. Я хотел начать новую тему, чтобы регулярно проверять RSS-канал на наличие обновлений.

Но вы не можете начать новый поток и вызывать из него компоненты графического интерфейса Eclipse. Вместо этого вы должны вызвать org.eclipse.swt.widgets.Display#asyncExec(Runnable)метод для выполнения кода в отдельном потоке. Но это не все. Сначала я реализовал свой Runnableкласс следующим образом:

Runnable checkFeed = new Runnable() {
    public void run() {
        while (true) {
            // check the feed
            try {
                Thread.sleep(30 * 1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

window.getShell().getDisplay().asyncExec(checkFeed);

Это, однако, не сработало, поскольку бесконечный whileцикл блокирует все действия графического интерфейса, включая всплывающее меню при щелчке правой кнопкой мыши на значке в системном трее.

Мне пришлось прекратить блокировать этот поток, поэтому я реализовал Runnableкласс следующим образом:

private long lastFeedCheck = 0;

private void launchFeedCheckingThread() {
    Runnable checkFeed = new Runnable() {
        public void run() {
            long now = System.currentTimeMillis();
            if (now - lastFeedCheck < 30000) {
                // sleep a little while to avoid being a CPU hog
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                // re-schedule this Runnable instance
                if (!window.getShell().getDisplay().isDisposed()) {
                    window.getShell().getDisplay().asyncExec(this);
                }
                return;             
            }
            try {
                // check the feed
            } finally {
                // update the timestamp variable to delay the
                // next feed check with 30 seconds
                lastFeedCheck = System.currentTimeMillis();
                // re-schedule this Runnable instance
                if (!window.getShell().getDisplay().isDisposed()) {
                    window.getShell().getDisplay().asyncExec(this);
                }
            }
        }
    }

    // launch the feed checking thread for the first time
    window.getShell().getDisplay().asyncExec(checkFeed);
}

Это эффективно освобождает поток с активностью GUI, отвечающей быстро. Несмотря на то, что приложение RCP работало хорошо при запуске из Eclipse, у меня возникли проблемы при экспорте автономного приложения.

В Eclipse экспортировать приложение RCP довольно просто. Сначала необходимо создать файл «Конфигурация продукта» («Создать» — «Другое» -> «Конфигурация продукта»). Здесь вы можете указать параметры развертывания, например добавить дополнительные плагины Eclipse.

Это работало нормально, пока я не добавил две библиотеки в приложение: rome.jarи jdom.jar. Я использую их, чтобы читать RSS-канал Hudson. Сначала я добавил их как библиотеку проектов в Eclipse, как вы это сделали бы в обычном проекте Java.

Однако этого недостаточно для их экспорта. Я попытался добавить их в build.propertiesфайл в Extra Classpath Entriesразделе. Это решило ошибку, которая ранее произошла при экспорте.

Но файлы JAR все еще не были включены в экспортируемое приложение. Не найдя другого обходного пути, я распаковал содержимое обоих JAR-файлов в корне проекта RCP и включил их для экспорта в build.propertiesфайл (см. Снимок экрана). Это эффективно включало в себя классифицированное обязательство в экспортируемом приложении 🙂

[Img_assist | NID = 420 | название = | убывание = | ссылка = нет | ALIGN = правая | ширина = 365 | высота = 281]

В целом мой первый проект в Eclipse RCP был очень легким. Eclipse API несколько переполнен, но все же интуитивно понятен для программирования. Тот факт, что классы Eclipse имеют прикрепленный исходный код, также упрощает работу.

Если вы хотите контролировать свой собственный сервер Hudson из панели задач, проверьте исходный код ( требуется версия Eclipse 3.3 plugin ) и двоичные файлы Windows.

Удачного кодирования!