Итак, как вы знаете, GemFire (и, как следствие, Apache Geode) хранит JSON в формате PDX (как PdxInstance). Это сделано для того, чтобы GemFire мог взаимодействовать со многими клиентами на разных языках (нативный C ++ / C #, веб-ориентированный (JavaScript, Pyhton, Ruby и т. Д.), Используя Developer REST API, в дополнение к Java), а также возможность использовать OQL для запроса данных JSON.
После небольших экспериментов я удивлен, что GemFire ведет себя не так, как я ожидал. Я создал пример автономного тестового класса (то есть, конечно, без Spring XD), который имитирует ваш вариант использования ... по существу, сохраняя данные JSON в GemFire как PDX, а затем пытаюсь прочитать данные обратно как объект домена приложения Order Типа с использованием абстракции Repository, достаточно логично.
Учитывая использование абстракции и реализации репозитория из Spring Data GemFire, инфраструктура попытается получить доступ к объекту домена приложения на основе параметра универсального типа репозитория (в данном случае «Порядок» из определения «Репозиторий»).
Однако данные хранятся в PDX, и что теперь?
Неважно, Spring Data GemFire предоставляет MappingPdxSerializer для преобразования экземпляров PDX обратно в объекты домена приложения с использованием тех же «метаданных сопоставления», которые использует инфраструктура репозитория. Круто, поэтому я воткну это ...
@Bean
public CacheFactoryBean gemfireCache(Properties gemfireProperties) {
CacheFactoryBean cacheFactoryBean = new CacheFactoryBean();
cacheFactoryBean.setProperties(gemfireProperties);
cacheFactoryBean.setPdxSerializer(new MappingPdxSerializer());
cacheFactoryBean.setPdxReadSerialized(false);
return cacheFactoryBean;
}
Вы также заметите, что я установил для свойства PDX 'read-serialized' (cacheFactoryBean.setPdxReadSerialized(false);
) значение false, чтобы гарантировать, что операции доступа к данным возвращают объект домена, а не экземпляр PDX.
Однако это никак не повлияло на метод запроса. Фактически, это не повлияло и на следующие операции ...
orderRepository.findOne(amazonOrder.getTransactionId());
ordersRegion.get(amazonOrder.getTransactionId());
Оба вызова вернули PdxInstance. Обратите внимание, что реализация OrderRepository.findOne(..)
основана на SimpleGemfireRepository.findOne (ключ), в котором используется GemfireTemplate.get (key), который выполняет только Region.get(key)
и т. д. фактически то же самое, что и (ordersRegion.get(amazonOrder.getTransactionId();
). Результат не должен быть таким, особенно если для Region.get()
и для чтения-сериализации установлено значение false.
С запросом OQL (SELECT * FROM /Orders WHERE transactionId = $1
), сгенерированным из findByTransactionId(String id)
, инфраструктура репозитория имеет немного меньший контроль над тем, что будет возвращать механизм запросов GemFire в зависимости от того, что ожидает вызывающий (OrderRepository) (на основе параметра универсального типа), поэтому выполнение операторов OQL потенциально может вести себя иначе, чем прямой доступ к региону с использованием get
.
Затем я попытался изменить тип Order
для реализации PdxSerializable, чтобы обрабатывать преобразование во время операций доступа к данным (прямой доступ к региону с помощью get, OQL или иным образом). Это не повлияло.
Итак, я попытался реализовать собственный PdxSerializer для Order
объектов. Это тоже не повлияло.
Единственное, что я могу сделать на данный момент, это что-то теряется при переводе между Order -> JSON -> PDX
и затем PDX -> Order
. По-видимому, GemFire нужны метаданные дополнительных типов, требуемые PDX (что-то вроде @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@type")
в данных JSON, которые распознает PDXFormatter, хотя я не уверен, что это так.
Обратите внимание, в моем тестовом классе я использовал ObjectMapper
Джексона для сериализации Order
в JSON, а затем JSONFormatter для сериализации JSON в PDX, что, как я подозреваю, Spring XD делает под капотом. Фактически, Spring XD использует Spring Data GemFire и, скорее всего, использует Поддержка JSON Region Auto Proxy. Это именно то, что SDG имеет JSONRegionAdvice объект имеет (см. здесь).
В любом случае, у меня есть запрос к остальной команде инженеров GemFire. В Spring Data GemFire также можно сделать кое-что, чтобы гарантировать преобразование данных PDX, например, использовать MappingPdxSerializer
напрямую для автоматического преобразования данных от имени вызывающего, если данные действительно имеют тип PdxInstance
. Подобно тому, как работает автоматическое проксирование области JSON, вы можете написать перехватчик AOP для области заказов, чтобы автоматически преобразовывать PDX в Order
.
Хотя я не думаю, что что-либо из этого должно быть необходимо, поскольку GemFire должен поступать правильно в этом случае. Извините, у меня сейчас нет лучшего ответа. Посмотрим, что я узнаю.
Ура и следите за обновлениями!
Смотрите следующий пост для тестового кода.
person
John Blum
schedule
03.09.2015