В продолжении исследований GWT в совокупности с dmServer я наткнулся на одну загадочную поначалу проблему – сериализация.
Что это такое сериализация. Я не буду рассматривать и рассказывать, что собой представляет сериализация и для чего она нужна – это вы можете легко узнать, благо в сети найдутся хорошие публикации на эту тему, в данном же контексту меня интересует сериализация, которую использует GWT-RPC. GWT-RPC – это подход, который используется в GWT для осуществления I/O общения между клиентской и серверной частами приложения. Этот подход позволяет оперировать с Java-объектами на стороне клиента, но есть определенное количество нюансов, о которых можно узнать по приведенной выше ссылке.
В моей ситуации произошла следующая ситуация. Мое приложение имеет слой для работы с базой данных с помошью JPA и в качестве JPA Provider я использую Hibernate. Так же у меня имеется DTOs, с которыми оперируют интерфейсы приложения, об Entity объектах знают только имплементации сервисных интерфейсов. Сервисы менеджется и публикуются в OSGi Service Registry Spring-ом. Клиентское приложение получает ссылку на сервис с помошью специального сервлета, который немного расширяет функционал RemoteServiceServlet и предоставляет возможность по названияю сервиса получать ссылку на него из Spring WebApplication Context.
И так собственно о проблемах:
- первая проблема возникла, когда я попытался получить в клиентском приложении сформированый из Entity DTO объект. У меня была ошибка сериализции, т.к. в качестве Primary Key я использую тип Long, а на сколько я знаю в JavaScript нет такого типа, то GWT эмулируют его с помошью double. Изменив, как рекомендуется документацией GWT, Long на Integer, моя проблема не исчезла. Я все также получал ошибку вида
Expected primitive type int; actual value was undefined
В итоге мне пришлось заменить типы Integer на int и эта пробема была устранена. Я смог получить DTO объект с серверной части приложения.
- следующей проблемой была сериализция типа java.util.Date. Мой DTO объект не десериализировался процесс валился на попытке создания инстанса объекта.
Продебажив и прогуглив в течении половины работчего дня и в виду наступления времени, когда уже приходится ложиться спать. Но сегодня с новыми силами и желаниями разобраться я продолжил. Странно, но дебаг ни Java, ни JavaScript когда мне не помогли, тогда пришла идея создать простое приложение и задеплоить его в контейнер. Попытка с простым war-ником (не OSGi Bundle) увенчалась успехом, что заставило задуматься. Посмотрев внимательно на содержимое директории WEB-INF/lib war-ника, это было не трудно, т.к. там всего лишь одна библиотека gwt-serlvet.jar – отсюда я сделал вывод, что нужно исправить заголовки в MANIFEST.MF этого бандла, что бы ему не нужны были зависимости от gwt-windows.jar и gwt-user.jar (что было в первом работчем варианте). Таким образом немножко изменив темплейты для MANIFEST.MF файлов gwt-serlvet.jar и моего приложения, все заработало. Темплейт для gwt-serlvet.jar должен выглядеть следующим образом:
Bundle-ClassPath: . Excluded-Imports: junit.framework, com.google.gwt.junit.client, com.google.gwt.core.client, com.google.gwt.util, com.google.gwt.benchmarks Import-Template: javax.servlet.*;version="[2.4.0,2.5.0]"
В темплейт же для моего war-ника я добавил к импорту пакетов еше и импорт бандла:
....... Import-Template: com.google.gwt.*;version="1.7.0", ....... Import-Bundle: gwt-servlet;version="1.7.0"
Проделав эти шаги проблема с сериализацией объектов Date исчезла.
На этом я не остановился, а попробовал вернуться к использования в качестве Primary Key объектов вместо примитивных типов и ура)) эта проблема тоже была устранена. К тому же мы избавились от зависимостей от бандлов gwt-windows.jar и gwt-user.jar.
Теперь можно двигаться дальше….