Статья-рецепт про удобную разработку на GWT в IDEA с помощью DCEVM

В IDEA, в отличие от Eclipse, при запуске проекта GWT с помощью стандартного плагина (и, как в последствие выяснилось, и без него, а просто запуск GWT DevMode — приложение для запуска в режиме разработки и debug’а, а конкретно com.google.gwt.dev.DevMode из gwt-dev.jar — как Java Application) при изменении UI кода нужно обновлять браузер, что бы изменения сработали. В случае GWT это очень критично — так как при обновлении страницы происходит повторное подключение к Code Server (сервер с исходным кодом проекта, нужен, что бы можно производить debug Java кода), а это занимает от 10 секунд до нескольких минут. Здесь я расскажу о способе, как менять код практически без перезагрузки страницы.Пример кода, на котором происходит ошибка:

IButton b = new IButton («Кнопка», new ClickHandler () { @Override public void onClick (ClickEvent event) { changedMethod (); } }); void changedMethod () { // Этот код можно изменить в run time. Window.alert («Изменяемый текст»); } Здесь в ClickHandler вызывается метод changedMethod (). При изменении тела этого метода, изменения в браузере не применяются без перезагрузки страницы. Т.е., например, если запустить приложение в котором будет эта кнопка, то при изменении текста «Изменяемый текст» на «Изменяемый текст 2» и нажатии на кнопку всё равно появится сообщение «Изменяемый текст». При обновлении страницы в браузере, изменения применятся.

Причина в том, что при обновлении классов hot swap (технология «горячей» замены кода, без перезапуска приложения) не срабатывает и не загружает изменённые классы, какие-бы мелкие изменения там не происходили.

Но есть расширенна «реализация» hot swap, которая позволяет ему работать — Dynamic Code Evolution VM (далее DCEVM), модификация JRE HotSpot для возможности загружать изменённые классы. От простого hot swap, который предоставляет JRE (и который в IDEA почему-то не работает) отличается большими возможностями — можно вносить изменения не только в тело метода, но и в его сигнатуру, а так же удалять/добавлять методы в классе и менять иерархию классов. Удалять и добавлять классы нельзя. ssw.jku.at/Research/Papers/Wuerthinger10a/Wuerthinger10a.pdf

Вообще есть plugin DCEVM для IDEA —, но он включает в себя только JRE, а она нам не подойдёт по двум причинам:1) Для запуска GWT plugin’а в IDEA нельзя указать JRE, под которой будет запускаться — будет запускаться под JDK проекта.2) Если всё же запустить DevMode, как Java Application и явно указать ему JRE DCEVM (как раз эта JRE появится после установки plugin’а), то DevMode не запуститься, так как не сможет запустить Swing. Судя по всему эта JRE не работает со Swing’ом.

Оригинальная версия находится: ssw.jku.at/dcevm/Но она уже как 3 года не поддерживается и не работает на Java 7 и 8, поэтому есть fork в котором это исправлено: github.com/dcevm/dcevmКачать от сюда: dcevm.github.io/

Я брал full версию Java 7 update 51, build 3.

Ставить нужно на JDK, под которой происходит разработка — она указана в настройках проекта. Ставить именно в JDK, т.к. из него потом запускается GWT plugin, ну и в дальнейшем будет работать для всех проектов. Установка по нажатию на кнопку «Replaced by DCEVM».

Ставил на Oracle HotSpot JDK 1.7.0_67×32 запущенный на win 7×64.

А дальше GWT приложение запускаем как обычно под debug’ом. После изменения класса выполняем Run→Reload Changed Classes и, если ошибок при компиляции нет, новые классы загрузятся (это будет указано в окне Event Log — что то вроде »<название конфигурации запуска>: 1 classes reloaded»).

Вообще, DCEVM подходит не только для GWT, а для всех случаев, когда hot swap не работает. Так что можно попробовать его на других проектах.

GWT 2.7 и отказ от plugin для браузера. Возможно, в GWT планируют отказаться от поддержки DevMode и plugin’ов для браузеров — уже сейчас GWT plugin для FireFox работает только максимум на 26 версии, а plugin для Chrome страшно тормозит. Поэтому я разрабатываю на FF 26.На замену ему уже существует SuperDevMode (www.gwtproject.org/articles/superdevmode.html). Вкратце, вместо исполнения клиентского Java кода, в режиме разработки, он позволяет компилировать Java код в JS и подгружать его в браузер. Т.е. фактически исполнятся будет JS, как и в production. Соотношение между JS и Java кодом работает с помощью Source Maps (технология в браузере, с помощью которой можно произвести соответствие строк кода между JS и кода, который в этот JS скомпилирован — для GWT это Java код) developer.chrome.com/devtools/docs/javascript-debugging#source-maps.

Но то, как позиционируется и реализована разработка в режиме SuperDevMode пока не подходит для реального применения. Есть несколько очень серьёзных минусов:1) Сейчас компилирование изменённого модуля происходит полностью, в не зависимости от того, изменили ли 1 класс или несколько. Для маленьких модулей это не проблема, но в случае больших модулей компиляция достигает 5–10 минут. И это, само собой, при отключение permutation и всего прочего.2) Debug этого кода непривычен — вместо обычного debug’а в IDE, предлагают использовать debug JS в самом браузере. Пример: geekbybit.blogspot.ru/2013/03/diy-working-with-gwt-codeserver-tomcat.html

В GWT 2.7 говорится об исправлении первого минуса — обещают ввести инкрементальную компиляцию. blog.oio.de/2014/03/31/upcoming-gwt-releases-2–7–3–0–2014-beyond/

И новая версия IDEA подготовила для нас приятный сюрприз — работу с SourceMaps docs.google.com/document/d/1Sf9lahq0jr0AsxR74ZE-Lntf0y5ZNk0104mhD8ozEuM/edit, youtrack.jetbrains.com/issue/WEB-4429#comment=27–620687Способ пока сырой, но это только начало.

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

P.S. Благодарность Andrey Dernov из JetBrains за помощь в исследовании проблемы.

© Habrahabr.ru