Tag Archives: GWT

GDD2010Moscow – I was there… #gddru #kyivgtug

На прошедших выходных мне довелось побывать на одном из запоминающихся мероприятий уходящего года – Google Developer Day 2010. Это мероприятие организованное компанией Google для разработчиков и просто людей, влюбленных в эту компанию и использующих её сервисы.

Мероприятие поразило своей организацией, масштабностью и количеством участников. Честно, я первый раз на мероприятии такого уровня. Хотелось бы отметить отзывчивость и готовность ответить на любой поставленный вопрос сотрудников Google – докладчиков. Среди них Michael Mahemoff, Paul Kinlan, Roman Nurik и Fred Sauer, с ними мне удалось пообщаться, а с некоторыми и сфотографироваться.

Roman Nurik (Android Developer Advocate from Google) and me
Roman Nurik (Android Developer Advocate from Google) and me

Как результат общения, удалось услышать информацию о возможности разработки расширений для Chrome на GWT и GWT Dev Plugin for Chrome on Linux, Fred сказал, что он часто слышит этот вопрос, и поспособствует сдвигу в этом направлении, что касается же Dev Mode в Chrome на Linux, то оказывается большинство разработчиков GWT используют Linux… вывод напрашиывается сам. К стати, для особо интересующихся тут есть проектик, с помошью которого можно создавать расширения используя GWT http://github.com/webdizz/gwt4chrome, а тут пример использования http://github.com/webdizz/terciman, само же расширение можно установить отсюда https://chrome.google.com/extensions/detail/kalnlennobeikiffcdhdnjpnmmbjdigi.

С Paul Kinlan и Michael Mahemoff была дискуссия про приложения и возможности монетизации, Paul является автором ряда приложений для twitter, и Michael тоже имеет ряд, но ни кто не пытался продавать свои творения, в прочем как и я… пока;)

Было очень круто, побывать на сцене  – мы – Andrey Yasinetskiy и я учавствовали в секции демо-презентаций. Презентовалось насше расширение, написанное в соавторстве с Timur Porkuyan и занявшее первое место на хаккатоне 23.10.10 в Киевском GTUG.  Расширение можно установить отсюда https://chrome.google.com/extensions/detail/ahmidlokhademhclkbapnlokgdhijjgj, а исходный код лежит тут http://github.com/Yasik/mapemall.

Вобщем впечатлений было масса.

За день же до вышеуказанного события мы, комманда GTUG из Киева, успели поучавствовать в хаккатоне и еще занять призовые места. На этот раз мы с Andrey Yasinetskiy испытывали свои силы в написании приложения для Android, за что получили по симпатичной мягкой игрушке с одноименным названием.

Следующий же день обещал быть не менее интересным – нам повезло посетить новый офис Google в Москве. Компания переехала туда только две недели назад и еще не было официальной презентации, но мы с удовольствием совершили это открытие, правда, фотографиорвать нам не разрешили, но зато очень приятно пообщались с Alexey Shelestenko и приходящими и уходящими сотрудниками попить кофе и других напитков.

Был очень смешной инцидент – мне хотели подарить футболку с логотипом GTUG размера XS (я даже не знал, что такой существует) – было очень много хохота, когда я достал её и попытался примерить…

Затем последовали часы ожидания поезда до Киева, которые мы провели на Арбате.

P.S. Огромное спасибо всем, кто принимал участие во всех вышеперечисленных мероприятиях.

P.P.S. Обзор о случившемся вы так же можете почитать тут.

GWT based Chrome extension

Доброго времени суток, однако прошел уже месяц с хвостиком с момента моего последнего опуса, но дабы не допустить возникновения паутины в собственном блоге хочу поделиться повествованием об освоении написания расширения для браузера Chrome.

Как обычно знакомство с чем-то новым и неизведанным является очень интересным и занимательным занятием, помимо этого еще и с присутствием “challenges” . Ближе к делу…

Итак в этот раз я взялся за написание плагина для Chrome. Я не буду описывать архитектуру API для написания расширений, т.к. заинтересовавшийся разработчик сможе ознакомиться с ней тут. Вкратце – плагин представляет собой файл-декларация плагина – manifest.json, background-html страницу (содержит общую логику расширения) и подключаемые js-файлы. Написание плагина на чистом JavaScript не представляет собой огромного интереса, в отличии от использования для этого GWT.

Как оказалось официальной поддержки Chrome extensions в GWT нет, но погуглив я наткнулся на кое-какую информацию по эьлму вопросу. В релиз GWT 2.0 включается расширение для Chrome Speed Tracer, которое написано с использованием GWT. Заложенные возможности к гибкому расширению с помошью GWT linker позволяют применять этот замечательный фреймворк очень широко.  Сделав чекаут проекта Speed Tracer я начал вникать в способ написания расширения. Как оказалось линкер в Speed Tracer не поддерживает ряд появившихся в новом API Chrome методов и типов, так мною были дописаны возможность подключать скрипты в background page, пости-инициализация подключаемых скриптов и немного доработан линкер до нужд моего расширения.

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

  • коммуникация между страницами и скриптами раширения – временно решена использованием паттерна Singleton;
  • логика перехвата событий должна находиться в подключаемых скриптах, т.к. они исполняются в контексте загруженной страницы.

На этом пока все, продолжение следует…

4kGadget v1.1-beta

Доброго времени суток!

На этот раз могу и хочу поделиться с вами небольшой информацией об изменениях в гаджете для сервиса 4Конверта.  Преследуя выполнение желаний пользователей гаджета и собственно своих, в работе над новой версией гаджета были произведены следующие изменения:

  • появилась возможность вносить изменения в регулярные траты и цели. Это можно сделать нажав на дату, для которой есть регулярные траты либо зачисления на цель -> в появившемся окне появились кнопки дл редактирования , нажав на которую появится поле для ввода суммы зачисления. Сумма будет занесена на цель для счета по-умолчанию после потери фокуса с поля ввода;
  • улучшения отображения в Chrome;
  • перевод на использование API 1.1 сервиса 4конверта;
  • перевод на GWT 2.0, в частности использование UiBinder в некоторых виджетах;
  • оптимизация и улучшение кода.

На этом все, всем спасибо.

Эффективного бюджетного планирования.

P.S. С удовольствием принимаются комментарии и пожелания.

Реализация MVP паттерна для GWT – Mvp4g – дополнения

Последнее время мое внимание привлекала технология для разработки RIA – GWT. И как это обычно бывает в каждом подходе и технологии есть свои достоинства и недостатки, и GWT не исключение. Но описание достоинств и недостатков этой технологии гораздо шире и объемнее того, что я хотел бы написать в данном посте. Я хочу сосредоточиться на использовании и о небольших правках, сделанных мной для реализации паттерна MVP – опен-сорс проекта Mvp4g.

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

При использовании этого фреймворка у меня возникла необходимость в обеспечении модулярности и возможности указания альтернативного конфигурационного файла.

Модулярность – под модулярностью понимается возможность указания дополнительного конфигурационного файла, который так же будет содержать декларации views,  presenters, services и events,  относящихся только к этому модулю. Так же при использовании GWT 2.x и указании аттрибута async активация данного подуля будет обвернута в RunAsyncCallback вызов, что в свою очередь обеспечит разделение вашего приложения на несколько отдельных частей и загрузка каждой части будет происходить только в случае необходимости. В целом же конфигурационный файл приложения, поддерживающего модульность не отличается от стандартного, за исключением следующего момента:

<module source="modules/module.xml" event="activationEvent" async="true"/>

Где source – указывает на файл конфигурации модуля, event – говорит на какое событие модуль будет активирован и async – указывает будет ли активация модуля обворачиваться в RunAsyncCallback вызов.

Еще одной доработкой является возможность указания дополнительного конфигурационного файла. Данная функциональность может пригодиться в таких случаях как, например, у вас есть админка, которая тоже построена на GWT, но вы не хотите фунционал админки с фронтендом мешать в одну кучу. Что же нужно для этого? Для этого нужно наследовать интерфейс com.mvp4g.client.Mvp4gStarter и аннотровать свой интерфейс с помошью аннотации com.mvp4g.client.Configuration, указав в качестве значения путь к альтернативному конфигурационному файлу. Затем в entry point классе создать имплементацию интерфейса с помощью GWT.create().

Пример интерфейса:

@Configuration("mvp4g-alt-conf.xml")
public interface CustomMvp4Starter extends Mvp4gStarter {}

Пример кода в  entry point классе:

public class TestMvp4gEntryPoint implements EntryPoint {
	private Mvp4gStarter entry;
 
	public void onModuleLoad() {
		entry = GWT.create(CustomMvp4Starter.class);
		entry.start();
	}
}

На этом все, скачать правки можно тут.

GWT-2.x and maven

Хочу поделиться скриптом, который мне помогает сохранить время при работе над GWT-2.x проектом. В виду того, что эта ветка находиться в постоянной разработке, но использование стабильной ветки не подходит, то необходимо периодически обновляться до актуальной версии. Мы используем Maven для сборки проекта и локальный репозиторий (Artifactory) и после каждого обновления нужно деплоить в репозиторий новые джарники. Что бы избавиться от рутины предлагаю воспользоваться следующим скриптом. Ни чего замысловатого – просто вызов mvn deploy-file …. Ниже собственно содержимое скрипта:

@echo off
 
echo ====================================================================================
echo Start deploying GWT artifacts
echo ====================================================================================
 
SET GWT_SDK_VERSION=2.0.0
SET GWT_SDK_PATH=D:\src\lib\gwt2\trunk\build\staging\gwt-windows-2.0.0
SET REPO=http://artifactory:8081/artifactory/libs-releases-local
SET LREPO=file:///D:\src\repository
 
echo ====================================================================================
echo Deploy gwt-servlet.jar
echo ====================================================================================
call mvn deploy:deploy-file -DrepositoryId=artifactory -Durl=%REPO% -DgeneratePom=true -DgroupId=com.google.gwt -Dversion=%GWT_SDK_VERSION% -Dpackaging=jar -Dfile=%GWT_SDK_PATH%/gwt-servlet.jar -DartifactId=gwt-servlet 
call mvn deploy:deploy-file -DrepositoryId=artifactory -Durl=%LREPO% -DgeneratePom=true -DgroupId=com.google.gwt -Dversion=%GWT_SDK_VERSION% -Dpackaging=jar -Dfile=%GWT_SDK_PATH%/gwt-servlet.jar -DartifactId=gwt-servlet 
 
echo ====================================================================================
echo Deploy gwt-user.jar
echo ====================================================================================
call mvn deploy:deploy-file -DrepositoryId=artifactory -Durl=%REPO% -DgeneratePom=true -DgroupId=com.google.gwt -Dversion=%GWT_SDK_VERSION% -Dpackaging=jar -Dfile=%GWT_SDK_PATH%/gwt-user.jar -DartifactId=gwt-user 
call mvn deploy:deploy-file -DrepositoryId=artifactory -Durl=%LREPO% -DgeneratePom=true -DgroupId=com.google.gwt -Dversion=%GWT_SDK_VERSION% -Dpackaging=jar -Dfile=%GWT_SDK_PATH%/gwt-user.jar -DartifactId=gwt-user 
 
echo ====================================================================================
echo Deploy gwt-dev-oophm.jar
echo ====================================================================================
call mvn deploy:deploy-file -DrepositoryId=artifactory -Durl=%REPO% -DgeneratePom=true -DgroupId=com.google.gwt -Dversion=%GWT_SDK_VERSION% -Dpackaging=jar -Dfile=%GWT_SDK_PATH%/gwt-dev-oophm.jar -DartifactId=gwt-dev-oophm 
call mvn deploy:deploy-file -DrepositoryId=artifactory -Durl=%LREPO% -DgeneratePom=true -DgroupId=com.google.gwt -Dversion=%GWT_SDK_VERSION% -Dpackaging=jar -Dfile=%GWT_SDK_PATH%/gwt-dev-oophm.jar -DartifactId=gwt-dev-oophm 
 
echo ====================================================================================
echo Deploy gwt-dev-windows.jar
echo ====================================================================================
call mvn deploy:deploy-file -DrepositoryId=artifactory -Durl=%REPO% -DgeneratePom=true -DgroupId=com.google.gwt -Dversion=%GWT_SDK_VERSION% -Dpackaging=jar -Dfile=%GWT_SDK_PATH%/gwt-dev-windows.jar -DartifactId=gwt-dev -Dclassifier=windows
call mvn deploy:deploy-file -DrepositoryId=artifactory -Durl=%LREPO% -DgeneratePom=true -DgroupId=com.google.gwt -Dversion=%GWT_SDK_VERSION% -Dpackaging=jar -Dfile=%GWT_SDK_PATH%/gwt-dev-windows.jar -DartifactId=gwt-dev -Dclassifier=windows
 
echo ====================================================================================
echo Deploy gwt-dev-windows-libs.zip
echo ====================================================================================
call mvn deploy:deploy-file -DrepositoryId=artifactory -Durl=%REPO% -DgeneratePom=true -DgroupId=com.google.gwt -Dversion=%GWT_SDK_VERSION% -Dpackaging=zip -Dfile=%GWT_SDK_PATH%/gwt-dev-windows.jar -DartifactId=gwt-dev -Dclassifier=windows-libs
call mvn deploy:deploy-file -DrepositoryId=artifactory -Durl=%LREPO% -DgeneratePom=true -DgroupId=com.google.gwt -Dversion=%GWT_SDK_VERSION% -Dpackaging=zip -Dfile=%GWT_SDK_PATH%/gwt-dev-windows.jar -DartifactId=gwt-dev -Dclassifier=windows-libs

4kGadget v1.0-beta

Хочу поделиться радостной, я так думаю, новостью для пользователей 4kGadget – iGoogle гаджета для сервиса 4конверта. Сегодня была завершена работа над новой версией гаджета, правильнее сказать он был переписан с чистого листа. Далее пересичлены моменты, которые доступны в связи с обновлением:

  • реализован функционал, доступный в прежней версии гаджета;
  • добавлена строка отображения состояния конверта в целом т.е. размер, сколько потрачено и сколько осталось денег в конверте;
  • немного улучшен интерфейс;
  • реализация базируется на GWT, что упрощает поддержку разных браузеров и увеличивает скорость работы гаджета, так же в будущем обеспечит легкость добавления новых фич;
  • гаджет теперь не зависит от фичи MiniMessage, доступной только в iGoogle;
  • гаджет теоретически должен работать в контейнере, поддерживающем стандарт OpenSocial (Google Calendar тоже;));

Для обеспечения работоспособности предыдущей версии гаджета его расположение не было изменено, но дальнейшая поддержка не будет осуществляться. Для установки новой версии гаджета рекомендуется удалить старую и открыть следующий URL в браузере: http://www.google.com/ig/adde?moduleurl=4kgadget.googlecode.com/svn/release/name.webdizz.gadget.four.envelope.Envelope.gadget.xml.

Приятного использования и бюджетного планирования.

P.S. Предложения и замечания как всегда приветствуются.

Google AppEngine first look

С недавних пор свое свободное время посвящаю реализации одной затеи в качестве платформы мы решили испоьзовать Google AppEngine для Java. И как оно обычно бывает с новыми и относительно неизвестными технологиями, с GAE это как оказалось – не исклбючение, появилось много проблем.

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

Начиналось все довольно спокойно – я установил SDK, поколдовал над рабочим окружением, что бы стало удобно работать и пустился в кодинг.

В моих планах было исследовать возможность работы Spring Framework 3.0.x, в частности меня интересует Spring MVC, а в качестве View – обычные старые добрые JSP. Со “спрингом” проблем особых не было, завелся, как говориться с пол пинка;).

Далее  – в качестве слоя для работы с базой взор был остановлен на JPA. Почему – потому что знакома и относительно привык работать с этой технологией. Но вот тут-то и начались “приколы”. Да на первый взгляд все заработало, но. Перечень “па” с бубном:

  • если вы используете Flex или GWT (как я) и хотите работать с объектами на стороне клиента, то одним из возможных подходов есть использование DTO объектов. В качестве конвертера объектов модели и объектов для клиентов я использую Dozer. И как оказалось в моем случае, из-за ограниченности в вариациях типов PrimaryKey, мне пришлось настраивать кастомные мапперы. В качестве PrimaryKey я использую предоставляемы Datastore тип Key, а клиент хранит его в виде строкового представления. До этого момента я получал сообщения об ошибках различного рода, связанные с ClassLoader-ом, с отсутствием поддержки типов ключей и т.д;
  • отсутствие поддержки связей. То есть если вам необходимо создать отношение One-To-Many, Many-To-Many или Many-To-One – у вас не будет возможности это сделать стандартным подходом. Это делается путем сохранения в ссылки на объект через его Key и последующей выборкой в случае необходимости. Не очень удобно, но работает. Надеюсь этого будет не всегда;
  • интересный нюанс с EntityManager.persist() или EntityManager.merge() – пока не вызовешь EntityManager.flush(), объект не будет сохранен. То есть если мне сразу же нужно вернуть сохраненный объект как результат выполнения метода, то я получу только то, что передал, хотя объект будет сохранен, но после.
  • еще вылезла проблема с использованием Spring Forms тегов. Немного погуглив, нашел решение проблемы – добавить в декларацию JSP аттрибут isELIgnored=”false” и переопределить PropertyEditors для каждого типа, используемого в бине, представляющем форму.

Так же еще одной из задач, которую нужно было решить – это подъем локального GAE сервера (в качестве сервлет контейнера используется Jetty) совместно с запуском GWT в дебаг-режиме. Тут конечно пришлось попотеть, т.к. стандартный подход Google к структуре проектов и отсутствие нативной поддержки с помощью Maven вынуждает к этому. Проблемы в основном были опять же с определением что откуда должно грузиться и совмещение это с тем, как мне нужно. После продолжительных не замысловатых действий вида “добавить ресурс, удалить ресурс” у меня все получилось. Теперь мой проект стартует из распакованного war-ника, поднимает Spring-контекст и подтягивает изменения в GWT на лету без перекомпиляции – то, что надо. Правда еще бы хотелось править JSP , без необходимости их последующего копирования в дерево проекта, но тогда придется жертвовать “чистотой” исходников проекта. Далее привожу свой конфиг для запуска GWT приложения в GAE контейнере.

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="org.eclipse.jdt.launching.localJavaApplication">
	<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
		<listEntry value="/webapp-ui" />
	</listAttribute>
	<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
		<listEntry value="4" />
	</listAttribute>
	<mapAttribute key="org.eclipse.debug.core.environmentVariables">
		<mapEntry key="JAVA_OPTS" value="-Xms128M -Xmx512M -XX:MaxPermSize=256M" />
		<mapEntry key="-Dappengine.sdk.root" value="D:\src\lib\gae-1.2.5" />
	</mapAttribute>
	<stringAttribute key="org.eclipse.debug.core.source_locator_id"
		value="org.eclipse.jdt.launching.sourceLocator.JavaSourceLookupDirector" />
	<stringAttribute key="org.eclipse.debug.core.source_locator_memento"
		value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;sourceLookupDirector&gt;&#13;&#10;&lt;sourceContainers duplicates=&quot;false&quot;&gt;&#13;&#10;&lt;container memento=&quot;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; standalone=&amp;quot;no&amp;quot;?&amp;gt;&amp;#13;&amp;#10;&amp;lt;javaProject name=&amp;quot;restio&amp;quot;/&amp;gt;&amp;#13;&amp;#10;&quot; typeId=&quot;org.eclipse.jdt.launching.sourceContainer.javaProject&quot;/&gt;&#13;&#10;&lt;container memento=&quot;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; standalone=&amp;quot;no&amp;quot;?&amp;gt;&amp;#13;&amp;#10;&amp;lt;javaProject name=&amp;quot;lib-controller&amp;quot;/&amp;gt;&amp;#13;&amp;#10;&quot; typeId=&quot;org.eclipse.jdt.launching.sourceContainer.javaProject&quot;/&gt;&#13;&#10;&lt;container memento=&quot;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; standalone=&amp;quot;no&amp;quot;?&amp;gt;&amp;#13;&amp;#10;&amp;lt;javaProject name=&amp;quot;lib-domain&amp;quot;/&amp;gt;&amp;#13;&amp;#10;&quot; typeId=&quot;org.eclipse.jdt.launching.sourceContainer.javaProject&quot;/&gt;&#13;&#10;&lt;container memento=&quot;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; standalone=&amp;quot;no&amp;quot;?&amp;gt;&amp;#13;&amp;#10;&amp;lt;javaProject name=&amp;quot;lib-model&amp;quot;/&amp;gt;&amp;#13;&amp;#10;&quot; typeId=&quot;org.eclipse.jdt.launching.sourceContainer.javaProject&quot;/&gt;&#13;&#10;&lt;container memento=&quot;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; standalone=&amp;quot;no&amp;quot;?&amp;gt;&amp;#13;&amp;#10;&amp;lt;javaProject name=&amp;quot;lib-service&amp;quot;/&amp;gt;&amp;#13;&amp;#10;&quot; typeId=&quot;org.eclipse.jdt.launching.sourceContainer.javaProject&quot;/&gt;&#13;&#10;&lt;container memento=&quot;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; standalone=&amp;quot;no&amp;quot;?&amp;gt;&amp;#13;&amp;#10;&amp;lt;javaProject name=&amp;quot;lib-service-impl&amp;quot;/&amp;gt;&amp;#13;&amp;#10;&quot; typeId=&quot;org.eclipse.jdt.launching.sourceContainer.javaProject&quot;/&gt;&#13;&#10;&lt;container memento=&quot;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; standalone=&amp;quot;no&amp;quot;?&amp;gt;&amp;#13;&amp;#10;&amp;lt;javaProject name=&amp;quot;mvp4g&amp;quot;/&amp;gt;&amp;#13;&amp;#10;&quot; typeId=&quot;org.eclipse.jdt.launching.sourceContainer.javaProject&quot;/&gt;&#13;&#10;&lt;container memento=&quot;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; standalone=&amp;quot;no&amp;quot;?&amp;gt;&amp;#13;&amp;#10;&amp;lt;javaProject name=&amp;quot;webapp-ui&amp;quot;/&amp;gt;&amp;#13;&amp;#10;&quot; typeId=&quot;org.eclipse.jdt.launching.sourceContainer.javaProject&quot;/&gt;&#13;&#10;&lt;/sourceContainers&gt;&#13;&#10;&lt;/sourceLookupDirector&gt;&#13;&#10;" />
	<listAttribute key="org.eclipse.jdt.launching.CLASSPATH">
		<listEntry
			value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry containerPath=&quot;com.google.appengine.eclipse.core.GAE_CONTAINER&quot; path=&quot;3&quot; type=&quot;4&quot;/&gt;&#13;&#10;" />
		<!-- GWT 2.x feature - ability to start HostedMode within browser -->
		<listEntry
			value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry externalArchive=&quot;D:/src/repository/com/google/gwt/gwt-dev-oophm/2.0.0/gwt-dev-oophm-2.0.0.jar&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;" />
		<listEntry
			value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry externalArchive=&quot;D:/src/repository/commons-configuration/commons-configuration/1.6/commons-configuration-1.6.jar&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;" />
		<listEntry
			value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry containerPath=&quot;com.google.gwt.eclipse.core.GWT_CONTAINER&quot; path=&quot;3&quot; type=&quot;4&quot;/&gt;&#13;&#10;" />
		<listEntry
			value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry externalArchive=&quot;D:/src/repository/name/webdizz/rest/io/lib-service/0.0.1/lib-service-0.0.1.jar&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;" />
		<listEntry
			value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry externalArchive=&quot;D:/src/repository/com/mvp4g/mvp4g/1.0-SNAPSHOT/mvp4g-1.0-SNAPSHOT.jar&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;" />
		<listEntry
			value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/gwt-widget/src/main/java&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;" />
		<listEntry
			value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/lib-domain/src/main/java&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;" />
		<listEntry
			value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/lib-service/src/main/java&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;" />
		<listEntry
			value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/gwt-base/src/main/java&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;" />
		<listEntry
			value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/webapp-ui/src/main/resources&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;" />
		<listEntry
			value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/webapp-ui/src/main/java&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;" />
		<listEntry
			value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/webapp-ui/src/main/webapp&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;" />
	</listAttribute>
	<stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER"
		value="org.maven.ide.eclipse.launchconfig.classpathProvider" />
	<booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH"
		value="false" />
	<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER"
		value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/1.6" />
	<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE"
		value="com.google.gwt.dev.HostedMode" />
	<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS"
		value="-startupUrl /view/&#13;&#10;-war D:\tmp\restio\webapp-ui\webapp-ui&#13;&#10;-server com.google.appengine.tools.development.gwt.AppEngineLauncher&#13;&#10;name.webdizz.rest.io.ui.Engine" />
	<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR"
		value="webapp-ui" />
	<stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER"
		value="org.maven.ide.eclipse.launchconfig.sourcepathProvider" />
	<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS"
		value="-Xmx512M" />
	<stringAttribute key="org.eclipse.jdt.launching.WORKING_DIRECTORY"
		value="D:\tmp\restio\webapp-ui\webapp-ui" />
</launchConfiguration>

Хотел было прокомментировать код, но начав, понял – это не очень уместно т.к. названия он интуитивно понятен.
На это все, продолжим исследования…

GWT 1.7 on SpringSource dm Server 2.0.0.M3 UPD

В продолжении исследований GWT в совокупности с dmServer я наткнулся на одну загадочную поначалу проблему – сериализация.

Что это такое сериализация. Я не буду рассматривать и рассказывать, что собой представляет сериализация и для чего она нужна – это вы можете легко узнать, благо в сети найдутся хорошие публикации на эту тему, в данном же контексту меня интересует сериализация, которую использует GWT-RPC. GWT-RPC – это подход, который используется в GWT для осуществления I/O общения между клиентской  и серверной частами приложения. Этот подход позволяет оперировать с Java-объектами на стороне клиента, но есть определенное количество нюансов, о которых можно узнать по приведенной выше ссылке.

В моей ситуации произошла следующая ситуация. Мое приложение имеет слой для работы с базой данных с помошью JPA и в качестве JPA Provider я использую Hibernate. Так же у меня имеется DTOs, с которыми оперируют интерфейсы приложения, об Entity объектах знают только имплементации сервисных интерфейсов. Сервисы менеджется и публикуются в OSGi Service Registry Spring-ом. Клиентское приложение получает ссылку на сервис с помошью специального сервлета, который немного расширяет функционал RemoteServiceServlet и предоставляет возможность по названияю сервиса получать ссылку на него из Spring WebApplication Context.
Continue reading GWT 1.7 on SpringSource dm Server 2.0.0.M3 UPD

Отладка GWT приложений на внешнем контейнере

Background

В предыдущем посте было упомянуто о необходимости запускать GWT приложение в Hosted Mode, используя при этом dmServer, тут же я бы хотел поделиться шагами, через которые мне пришлось пройти, чтобы реализовать эту возможность.

Итак как это было…

Прочитав FAQ тут, как говорится с “пол пинка” не завелось к сожалению( Но на этом мое намерение отлаживать мое приложение в dmServer не испарилось. Что я сделал – изменил настройки ланчера для запуска приложения в Hosted Mode: изменил параметр для открытия URL -startupUrl и добавил парметр, говорящий ланчеру не запускать встроенный сервлет контейнер (для GWT 1.7 – Jetty). Содержимое конфигурационного файла приведено ниже.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="org.eclipse.jdt.launching.localJavaApplication">
	<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
		<listEntry value="/stock-watcher" />
	</listAttribute>
	<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
		<listEntry value="4" />
	</listAttribute>
	<booleanAttribute key="org.eclipse.debug.core.appendEnvironmentVariables"
		value="true" />
	<listAttribute key="org.eclipse.jdt.launching.CLASSPATH">
		<listEntry
			value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry containerPath=&quot;org.eclipse.jdt.launching.JRE_CONTAINER&quot; javaProject=&quot;stock-watcher&quot; path=&quot;1&quot; type=&quot;4&quot;/&gt;&#13;&#10;" />
		<listEntry
			value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/stock-watcher/src/main/java&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;" />
		<listEntry
			value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry id=&quot;org.eclipse.jdt.launching.classpathentry.defaultClasspath&quot;&gt;&#13;&#10;&lt;memento exportedEntriesOnly=&quot;false&quot; project=&quot;stock-watcher&quot;/&gt;&#13;&#10;&lt;/runtimeClasspathEntry&gt;&#13;&#10;" />
	</listAttribute>
	<stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER"
		value="org.maven.ide.eclipse.launchconfig.classpathProvider" />
	<booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH"
		value="false" />
	<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE"
		value="com.google.gwt.dev.HostedMode" />
	<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS"
		value="-startupUrl http://localhost:8080/stock-watcher/StockWatcher.html&#13;&#10;name.webdizz.gwt.stock.watcher.StockWatcher&#13;&#10;-war src/main/webapp&#13;&#10;-noserver" />
	<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR"
		value="stock-watcher" />
	<stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER"
		value="org.maven.ide.eclipse.launchconfig.sourcepathProvider" />
	<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS"
		value="-Xmx256M" />
</launchConfiguration>

На этом мои действия, исходя из смысла приведенной выше статьи, должны были увенчаться успехом, но это было не совсем так. Дальнейшие “танцы с бубном” показали, что так как я использую Maven для сборки проекта и, в частности, gwt-maven-plugin для компиляции GWT специфичных артифактов, проблема скрывалась за несогласованными действиями Google Eclipse plugin и Maven. Этот момент был устранен настройкой maven-war-plugin в файле pom.xml проекта stock-watcher. Я исключил копирование содержимого директории src/main/webapp/stockwatcher из src/main/webapp/ (директива warSourceExcludes).

46
47
48
49
50
51
52
<plugin>
	<groupId>org.apache.maven.plugins</groupId>
	<artifactId>maven-war-plugin</artifactId>
	<configuration>
		<warSourceExcludes>**/stockwatcher/**</warSourceExcludes>
	</configuration>
</plugin>

`После этого собранный проект с помошью команды

mvn clean install

Результат сборки копируем в pickup директорию dmServer-а и запускаем ланчер в Eclipse. Ставим breakpoint и наслаждаемся…;) правда перед тем как окунуться в дебаг не знаю почему, но необходимо Hosted Browser рефрешить 5 раз и на 6-ой мы попадаем на точку останова)).

Debugging GWT application
Debugging GWT application