Instalación y actualización > Actualización de ThingWorx > Migración de las extensiones de Java de 8.x a 9.x
Migración de las extensiones de Java de 8.x a 9.x
Puede que solo sea necesaria la migración de las extensiones de Java de copia de seguridad. La migración de las extensiones de Java solo es necesaria si se actualiza de ThingWorx 8.x a 9.x (no de 9.x a 9.x) y si se dispone de lo siguiente:
Eventos de ciclo de vida implementados, tales como initializeEntity y cleanupEntity
Se mantiene el estado local en la implementación.
Se tienen copias locales (o referencias fijas) de otras entidades.
En la agrupación de alta disponibilidad de ThingWorx, existen entidades en varios servidores. Su información debe permanecer sincronizada entre servidores. Su ciclo de vida es un poco diferente en el servidor donde se produce el cambio (servidor de cambios) y el servidor en el que se sincronizan los cambios (servidor de sincronización). Solo hay un servidor de cambios y todos los demás servidores del clúster son servidores de sincronización, que vuelven a cargar las entidades no válidas. El servidor de cambios es simplemente el servidor en el que aterriza la solicitud; no tiene estado ni configuración especiales.
Se ha añadido un nuevo atributo de metadatos de extensión, haCompatible, para identificar si una extensión es compatible con la agrupación de alta disponibilidad de ThingWorx. Para obtener más información, consulte Prácticas recomendadas para empaquetar e implementar soluciones de ThingWorx y Configuración de plataforma para la alta disponibilidad de ThingWorx.
Cambios de API de ciclo de vida 
Con la agrupación de alta disponibilidad de ThingWorx, los siguientes métodos de API de ciclo de vida requieren ahora un parámetro adicional. El motivo del cambio es la diferencia de comportamiento en el ciclo de vida del servidor de cambios frente a los servidores de sincronización. En el servidor de cambios, se debe realizar toda la lógica para el evento de ciclo de vida. Sin embargo, en los servidores de sincronización, es posible que solo desee realizar un subconjunto de esta lógica. Por ejemplo, durante la inicialización, no hay ningún motivo para definir todos los estados en los servidores de sincronización, ya que el estado es compartido.
Con el parámetro ContextType, se puede decidir si se debe ejecutar parte de la lógica. Un parámetro ContextType con el valor NONE indica que no es una operación secundaria y que se debe ejecutar toda la lógica. El parámetro ContextType también puede diferenciar entre STARTUP, SHUTDOWN, INSERT, UPDATE o DELETE, que activan diferentes comportamientos.
Estos cambios crearán errores en tiempo de compilación. Para una corrección de un único servidor, se puede añadir el parámetro a los métodos y no es necesario ningún otro cambio. Para obtener compatibilidad con la agrupación activa-activa, realice los siguientes cambios:
initializeEntity() a initializeEntity(contextType)
cleanupEntity() a cleanupEntity(contextType)
initializeThing() a initializeThing(contextType)
startThing() a startThing(contextType)
processStartNotification() a processStartNotification(contextType)
stopThing() a stopThing(contextType)
cleanupThing() a cleanupThing(contextType)
En el siguiente ejemplo de la entidad de cosa, al inicializar el servidor de cambios, se realiza una actualización completa de la tabla de configuración desde su jerarquía y se almacenan los cambios. En el servidor de sincronización, la tabla de configuración se actualiza cuando se inicializa la entidad. Puesto que ya se ha almacenado en la base de datos, se puede cargar. No es necesario recorrer la jerarquía ni realizar otra lógica.
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);
}
En la operación de limpieza, el comportamiento es similar. La información en caché del servidor de cambios se despeja, pero no lo hace en el servidor de sincronización ya que el estado se comparte. En general, el servidor de cambios realiza todo el trabajo y el servidor de sincronización hace menos.
public void cleanupEntity(ContextType contextType) throws Exception {
super.cleanupEntity(contextType);
getInstanceShape().cleanup(contextType);
// reset cache
if (!contextType.isSecondaryOperation()) {
clearNonPersistentPropertiesFromCache();
clearLastPropertyValueCache();
}
if (isEnabled()) {
cleanupThing(contextType);
}
}
Mantenimiento del estado 
El estado local es cualquier estado que no se encuentre en propiedades, tablas de configuración o tablas de datos. El estado local debe cambiarse a estado compartido para que esté disponible entre servidores. El estado compartido se lleva a cabo con la capa de caché de Ignite. En el caso de las extensiones, se recomienda almacenar todos los estados en propiedades o en tablas de configuración:
Tablas de configuración
Las tablas de configuración se almacenan en la base de datos y se sincronizan entre todos los servidores. Por lo tanto, se produce una ligera demora en la actualización entre los servidores. Puesto que las tablas de configuración forman parte de la sincronización del modelo, las entidades del servidor de sincronización se destruyen y se vuelven a crear con el modelo cambiado cuando se sincroniza. Por lo tanto, puede ser más ordenado y más eficaz utilizar propiedades en lugar de actualizaciones de todo el modelo. Asimismo, las propiedades persistentes se pueden utilizar para almacenar valores de estado entre reinicios.
Propiedades
Ahora todos los valores de propiedad se almacenan como estado compartido. Las actualizaciones de estos valores se realizan inmediatamente en los servidores escribiendo en la caché. Si una propiedad es persistente, permanecerá almacenada en caché para mejorar el rendimiento y se escribirá en la base de datos para conservar el estado entre los reinicios. Se puede crear una cosa de datos, que puede contener propiedades de estado si es necesario que sean comunes en varias instancias de cosa.
Propiedades locales
En algunos casos, no se debe utilizar el estado compartido para las propiedades. Por ejemplo, ConnectableThing tiene la propiedad isConnected por la que se realiza el seguimiento del estado de conexión por servidor. No tiene sentido hacer que cada servidor sobrescriba isConnected cuando cambie su estado de conexión ConnectableThings. Este estado local se puede conseguir añadiendo el aspecto isLocalProperty a la propiedad. Este aspecto solo se aplica a las propiedades que no son persistentes; las propiedades persistentes con este aspecto se comparten como normales.
@ThingworxPropertyDefinition(
name ="isConnected",
description ="Flag indicating if connected or not",
baseType ="BOOLEAN",
aspects = {"isPersistent:false","isReadOnly:false","defaultValue:false","isLocalProperty:true"})
Verificación de referencias fijas 
Al desacoplar, se quitan las referencias fijas a otras entidades. En el proceso de revisión de la sincronización de modelos de la agrupación de alta disponibilidad de ThingWorx, el sistema necesita intercambiar las entidades modificadas. Por lo tanto, no puede haber entidades que encapsulen referencias fijas a otras entidades. Por ejemplo, si hay una plantilla de cosa almacenada en caché en el nivel de cosa y la plantilla cambia, se tendría que revisar en todos los servidores. Cualquier cosa que tenga una referencia fija a esta plantilla se romperá. Por lo tanto, se deben cambiar en todas las entidades las referencias fijas por referencias flexibles. Así, cuando se necesitan las referencias, la plataforma recorre el árbol para obtenerlas.
Por ejemplo, a continuación, se muestra la clase ThingTemplate que tiene una referencia a una plantilla de cosa base.
Con referencia fija
// 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;
}
Puesto que la referencia fija se almacena en _baseThingTemplate, se producirán problemas en la revisión del proceso de sincronización. En el siguiente ejemplo, la referencia fija se desacopla a una referencia flexible y solo se almacena el nombre y la plantilla se recupera cuando es necesario.
//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;
}
¿Fue esto útil?