Installazione e aggiornamento > Aggiornamento di ThingWorx > Migrazione delle estensioni Java da 8.x a 9.x
Migrazione delle estensioni Java da 8.x a 9.x
La migrazione delle estensioni è necessaria solo per le estensioni Java. La migrazione delle estensioni di Java è necessaria solo se si esegue l'aggiornamento da ThingWorx 8.x a 9.x (non da 9.x a 9.x) e nelle situazioni seguenti:
Eventi di ciclo di vita implementati quali initializeEntity e cleanupEntity
Mantenimento dello stato locale all'interno dell'implementazione
Presenza di copie locali (o riferimenti diretti) di altre entità
Nel clustering a disponibilità elevata di ThingWorx le entità esistono in più server. Le informazioni devono rimanere sincronizzate tra i server. Il ciclo di vita è leggermente diverso nel server in cui si verifica la modifica (server di modifica) rispetto a quello in cui le modifiche vengono sincronizzate (server di sincronizzazione). Esiste un solo server di modifica e tutti gli altri server del cluster sono server di sincronizzazione, che ricaricano le entità modificate ma non salvate. Il server di modifica è semplicemente il server che viene raggiunto dalla richiesta; non ha una configurazione o uno stato speciale.
È stato aggiunto un nuovo attributo di metadati delle estensioni (haCompatible) per identificare se un'estensione è compatibile con il clustering a disponibilità elevata ThingWorx. Per ulteriori informazioni, vedere Best practice per la creazione di package e la distribuzione di soluzioni ThingWorx e Impostazioni di piattaforma per ThingWorx a disponibilità elevata.
Modifiche alle API del ciclo di vita 
Con il clustering a disponibilità elevata di ThingWorx, i metodi API del ciclo di vita riportati di seguito richiedono ora un parametro aggiuntivo. Il motivo della modifica è la differenza di comportamento del ciclo di vita sul server di modifica rispetto ai server di sincronizzazione. Nel server di modifica è necessario che venga eseguita tutta la logica per l'evento del ciclo di vita. Nei server di sincronizzazione, invece, è possibile eseguire anche solo un sottoinsieme di questa logica. Ad esempio, durante l'inizializzazione non vi è alcun motivo per impostare tutti gli stati sui server di sincronizzazione perché lo stato è condiviso.
Il parametro ContextType consente di stabilire se eseguire una parte della logica. Se il valore del parametro ContextType è NONE, non si tratta di un'operazione secondaria e deve essere eseguita tutta la logica. ContextType può inoltre distinguere tra STARTUP, SHUTDOWN, INSERT, UPDATE e DELETE, che attivano comportamenti diversi.
Queste modifiche creano errori in fase di compilazione. Per correggere gli errori sui singoli server, è possibile aggiungere il parametro ai metodi. Non sono necessarie altre modifiche. Per garantire la compatibilità con il clustering attivo-attivo, apportare le modifiche seguenti:
Da initializeEntity() a initializeEntity(contextType)
Da cleanupEntity() a cleanupEntity(contextType)
Da initializeThing() a initializeThing(contextType)
Da startThing() a startThing(contextType)
Da processStartNotification() a processStartNotification(contextType)
Da stopThing() a stopThing(contextType)
Da cleanupThing() a cleanupThing(contextType)
Nell'esempio che segue relativo all'entità oggetto, quando il server di modifica viene inizializzato, viene eseguito un aggiornamento completo della tabella di configurazione dalla relativa gerarchia e le modifiche diventano permanenti. Nel server di sincronizzazione la tabella di configurazione viene aggiornata quando viene inizializzata l'entità. Poiché è già stato reso persistente nel database, può essere caricato. Non è necessario esplorare la gerarchia o eseguire altra logica.
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);
}
Nell'operazione di pulizia il comportamento è analogo. Le informazioni sulla cache sono deselezionate sul server di modifica ma non sul server di sincronizzazione perché lo stato è condiviso. In generale, la maggior parte del lavoro viene eseguito dal server di modifica.
public void cleanupEntity(ContextType contextType) throws Exception {
super.cleanupEntity(contextType);
getInstanceShape().cleanup(contextType);
// reset cache
if (!contextType.isSecondaryOperation()) {
clearNonPersistentPropertiesFromCache();
clearLastPropertyValueCache();
}
if (isEnabled()) {
cleanupThing(contextType);
}
}
Mantenimento dello stato 
Lo stato locale è qualsiasi stato che non si trovi nelle proprietà, nelle tabelle di configurazione o nelle tabelle dati. Per essere disponibile in più server, deve essere modificato in stato condiviso. È possibile ottenere lo stato condiviso con il livello di memorizzazione nella cache di Ignite. Per le estensioni, è consigliabile memorizzare tutti gli stati nelle proprietà o nelle tabelle di configurazione.
Tabelle di configurazione
Le tabelle di configurazione vengono memorizzate nel database e sincronizzate nei server. Di conseguenza, si verifica un lieve ritardo nell'aggiornamento nei server. Poiché le tabelle di configurazione fanno parte della sincronizzazione del modello, le entità nel server di sincronizzazione vengono distrutte e ricreate con il modello modificato durante la sincronizzazione. Pertanto, potrebbe risultare più efficace e lineare utilizzare le proprietà anziché gli aggiornamenti dell'intero modello. Utilizzando le proprietà persistenti, è inoltre possibile memorizzare i valori di stato tra un riavvio e l'altro.
Proprietà
Tutti i valori delle proprietà vengono ora memorizzati come stato condiviso. Gli aggiornamenti di questi valori avvengono immediatamente nei server mediante la scrittura nella cache. Se una proprietà è persistente, viene comunque memorizzata nella cache per le prestazioni e scritta nel database per mantenere lo stato tra un riavvio e l'altro. È possibile creare un oggetto dati che può contenere le proprietà di stato, se è necessario che siano comuni in più istanze di oggetto.
Proprietà locali
In alcuni casi la condivisione dello stato per le proprietà non deve essere utilizzata. Ad esempio, in ConnectableThing lo stato di connessione della proprietà isConnected viene monitoratoper ciascun server. Non ha senso sovrascrivere isConnected in ogni server quando cambia lo stato della connessione ConnectableThings. Questo stato locale può essere ottenuto aggiungendo l'aspetto isLocalProperty alla proprietà. Questo aspetto si applica solo alle proprietànon persistenti. Le proprietà persistenti con questo aspetto sono normalmente condivise.
@ThingworxPropertyDefinition(
name ="isConnected",
description ="Flag indicating if connected or not",
baseType ="BOOLEAN",
aspects = {"isPersistent:false","isReadOnly:false","defaultValue:false","isLocalProperty:true"})
Controllo dei riferimenti diretti 
Il disaccoppiamento rimuove i riferimenti diretti ad altre entità. Per il processo di applicazione di patch nella sincronizzazione dei modelli nel clustering a disponibilità elevata di ThingWorx, il sistema deve passare da un'entità modificata all'altra. Di conseguenza, non possono essere presenti entità che incapsulano riferimenti diretti ad altre entità. Ad esempio, se un modello di oggetto memorizzato nella cache a livello di oggetto viene modificato, è necessario applicare le patch su tutti i server. Qualsiasi oggetto con un riferimento diretto a questo modello viene interrotto. Pertanto, tutte le entità devono essere modificate da riferimento diretto a indiretto. Poiché sono necessari i riferimenti, la piattaforma esplora l'albero per ottenerli.
Ad esempio, di seguito è riportata la classe ThingTemplate con un riferimento a un modello di oggetto di base.
Con riferimento diretto
// 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;
}
Poiché il riferimento diretto viene memorizzato in _baseThingTemplate, si verificano problemi con l'applicazione di patch del processo di sincronizzazione. Nell'esempio riportato di seguito il riferimento diretto viene disaccoppiato da un riferimento indiretto e viene semplicemente memorizzato il nome e recuperato il modello quando necessario.
//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;
}
È stato utile?