Установка и обновление > Обновление ThingWorx > Перенос расширений Java с 8.x на 9.x
Перенос расширений Java с 8.x на 9.x
Перенос может потребоваться только для расширений на основе Java. Перенос расширений Java требуется только при обновлении от ThingWorx 8.x до 9.x (не от 9.x до 9.x) и при наличии следующих элементов:
Реализованные события жизненного цикла, такие как initializeEntity и cleanupEntity
Поддерживаемое локальное состояние в вашей реализации
Наличие локальных копий (или жестких привязок) других сущностей
В кластеризации ThingWorx с высокой доступностью сущности находятся на нескольких серверах. Их информация должна поддерживаться синхронизированной между серверами. Их жизненный цикл немного отличается на сервере, на котором происходит изменение (сервер изменений), и на сервере, на котором синхронизируются изменения (сервер синхронизации). Существует только один сервер изменений, а все остальные серверы в кластере являются серверами синхронизации, которые перезагружают "грязные" сущности. Сервер изменений - это просто сервер, на который приходят запросы; у него нет специальной конфигурации или статуса.
Добавлен новый атрибут метаданных расширения, haCompatible, чтобы определить, совместимо ли расширение с кластеризацией ThingWorx высокой доступности. Дополнительные сведения см. в разделах Рекомендации по упаковке и развертыванию решений ThingWorx и Настройки платформы для ThingWorx высокой доступности.
Изменения интерфейса API жизненного цикла 
При использовании кластеризации ThingWorx высокой доступности для следующих методов интерфейса API жизненного цикла теперь требуется дополнительный параметр. Причиной изменения является различие в поведении в жизненном цикле на сервере изменений по сравнению с серверами синхронизации. На сервере изменений вся логика должна быть выполнена для события жизненного цикла. Однако на серверах синхронизации может потребоваться выполнять только подмножество этой логики. Например, при инициализации нет причин задавать все состояния на серверах синхронизации, так как состояние является общим.
С помощью параметра ContextType можно решить, будет ли выполняться какая-то часть логики. Параметр ContextType со значением NONE показывает, что эта часть не является дополнительной операцией и должна выполняться вся логика. ContextType может также различать STARTUP, SHUTDOWN, INSERT, UPDATE или DELETE, что инициирует различные варианты поведения.
Эти изменения могут приводить к ошибкам времени компиляции. Для исправления в среде с одним сервером можно добавить параметр в методы, и никакие изменения не потребуются. Для совместимости с активно-активной кластеризацией измените следующее:
initializeEntity() на initializeEntity(contextType)
cleanupEntity() на cleanupEntity(contextType)
initializeThing() на initializeThing(contextType)
startThing() на startThing(contextType)
processStartNotification() на processStartNotification(contextType)
stopThing() на stopThing(contextType)
cleanupThing() на cleanupThing(contextType)
В приведенном ниже примере из сущности вещи при инициализации сервера изменений выполняется полное обновление таблицы конфигурации из ее иерархии, и изменения сохраняются. На сервере синхронизации таблица конфигурации обновляется при инициализации сущности. Так как она уже сохранена в базе данных, ее можно загружать. Нет необходимости выполнять обход иерархии или выполнять другую логику.
public void initializeEntity(ContextType contextType) throws Exception {
_logger.trace("initializeEntity called on Thing {} with patch operation {} ", getName(), contextType);
if (!contextType.isSecondaryOperation()) {
updateConfigurationTableStructure(contextType, null,
ThingShapeUtilities.getConfigurationTableDataForInheritance(getThingTemplate(), getImplementedThingShapes()));
} else {
updateConfigurationTableStructure(contextType);
}
super.initializeEntity(contextType);
}
В операции очистки данных поведение аналогично. Кэш очищается на сервере изменений, но не на сервере синхронизации, так как это состояние является общим. В общем случае сервер изменений выполняет все операции, а сервер синхронизации выполняет меньше работы.
public void cleanupEntity(ContextType contextType) throws Exception {
super.cleanupEntity(contextType);
getInstanceShape().cleanup(contextType);
// reset cache
if (!contextType.isSecondaryOperation()) {
clearNonPersistentPropertiesFromCache();
clearLastPropertyValueCache();
}
if (isEnabled()) {
cleanupThing(contextType);
}
}
Поддержание состояния 
Локальное состояние - это любое состояние, которое не находится в свойствах, таблицах конфигурации или таблицах данных. Локальное состояние должно быть изменено на общее состояние, чтобы быть доступным для разных серверов. Общее состояние выполняется с помощью слоя кэширования Ignite. Для расширений рекомендуется сохранять все состояния в свойствах или в таблицах конфигурации:
Таблицы конфигурации
Таблицы конфигурации сохраняются в базе данных и синхронизируются между серверами. Поэтому существует небольшая задержка в обновлении между серверами. Поскольку таблицы конфигурации являются частью синхронизации модели, сущности на сервере синхронизации уничтожаются и повторно создаются вместе с изменениями модели при синхронизации. Таким образом, использование свойств может оказаться более чистым и эффективным способом, чем обновление всей модели. Кроме того, постоянные свойства могут использоваться для хранения значений состояния между перезапусками.
Свойства
Все значения свойств теперь сохраняются как общее состояние. Обновления этих значений происходят непосредственно на серверах путем записи в кэш. Если свойство является постоянным, оно по-прежнему кэшируется для повышения производительности и записывается в базу данных для сохранения состояния между перезапусками. Можно создать вещь данных, которая может содержать свойства состояния, если они должны быть общими для нескольких экземпляров вещи.
Локальные свойства
В некоторых случаях нельзя использовать состояние общего доступа для свойств. Например, ConnectableThing имеет свойство isConnected, для которого отслеживается статус соединения по серверам. Нет смысла заставлять каждый сервер переписывать isConnected, когда изменяется его статус соединения ConnectableThings. Это локальное состояние можно получить, добавив к свойству аспект isLocalProperty. Этот аспект применяется только к свойствам, которые не являются постоянными; постоянные свойства с этим аспектом имеют общий доступ как нормальное состояние.
@ThingworxPropertyDefinition(
name ="isConnected",
description ="Flag indicating if connected or not",
baseType ="BOOLEAN",
aspects = {"isPersistent:false","isReadOnly:false","defaultValue:false","isLocalProperty:true"})
Проверка наличия жестких связей 
При разрыве связей удаляются жесткие связи с другими сущностями. Для процесса загрузки исправлений при синхронизации модели в ThingWorx кластере высокой доступности (HA) система должна обмениваться измененными сущностями. Поэтому не могут присутствовать сущности, инкапсулирующие жесткие привязки к другим объектам. Например, если имеется измененяемый шаблон вещи, кэшированный на уровне вещи, он должен быть исправлен на всех серверах. Любая жесткая привязка вещи к этому шаблону будет разорвана. Таким образом, во всех сущностях жесткие привязки должны быть изменены на мягкие. По мере необходимости платформа проходит по дереву, чтобы получить привязки.
Например, ниже приведен класс ThingTemplate, имеющий привязку к базовому шаблону вещи.
С жесткой привязкой
// Parent thing template
privateThingTemplate _baseThingTemplate =null
...
@ThingworxExtensionApiMethod(since = {6,6})
publicThingTemplate getBaseThingTemplate() {
if(_baseThingTemplate ==null&& StringUtilities.isNonEmpty(getBaseThingTemplateName())) {
_baseThingTemplate = ThingTemplateManager.getInstance().getEntityDirect(getBaseThingTemplateName());
}
return_baseThingTemplate;
}
Поскольку жесткая привязка сохраняется в _baseThingTemplate, это приведет к проблемам с исправлениями в процессе синхронизации. В приведенном ниже примере жесткая привязка разрывается и заменяется на мягкую привязку, причем сохраняется только наименование, а шаблон загружается при необходимости.
//Note the hard reference is removed (local stored template _baseThingTemplate)
@ThingworxExtensionApiMethod(since = {6,6})
publicThingTemplate getBaseThingTemplate() {
ThingTemplate baseThingTemplate =null
if(StringUtilities.isNonEmpty(getBaseThingTemplateName())) {
baseThingTemplate = ThingTemplateManager.getInstance().getEntityDirect(getBaseThingTemplateName());
}
returnbaseThingTemplate;
}
Было ли это полезно?