8.1 to 8.3 SDK Upgrade Guide
Please read this page carefully to ensure you are aware of any special considerations and actions required to successfully upgrade an existing module or develop a new 8.3 module. The following sections detail API changes made from 8.1 to 8.3, and are organized by subsystem.
Coreβ
Module Lifecycleβ
The lifecycle of modules has changed in Ignition 8.3. Modules are no longer started or stopped while the Gateway is already running. Instead, they are set up and started as the Gateway is starting, and shut down as the Gateway is shutting down. Any module changes while the Gateway is running will wait until a Gateway restart to take effect.
This change did not change the signatures of GatewayModuleHookβs lifecycle methods:
- setup(GatewayContext)
- startup(LicenseState)
- shutdown()
Modules in the user-lib/modules
folder will no longer automatically be loaded on startup without a corresponding entry in data/modules.json
indicating positive acceptance of the module.
Gateway Networkβ
Java serialization is no longer supported for 8.3 to 8.3 Gateway Network Communication (Java serialization will still be supported for 8.1 to 8.3 Gateway Network Communication as needed). Java objects that are sent between 8.3 Gateways over the Gateway Network must now provide a Protobuf implementation class for the object. To do so, an implementation of the com.inductiveautomation.metro.api.ProtobufSerializable
interface must be created, which can convert the Java object to a Protobuf object suitable for serialization. This implementation class must be registered in the Gateway Network using com.inductiveautomation.metro.api.MetroProtobufRegistry#register()
.
Note that 7.9 Gateways will not be allowed to connect to 8.3 Gateways, even over a proxy Gateway Network connection.
Method Changesβ
8.1 Method | 8.3 Method |
---|---|
GatewayAreaNetworkManager | GatewayNetworkManager |
GatewayAreaNetworkManagerImpl | GatewayNetworkManagerImpl |
Securityβ
The following APIs were moved from gateway-api
to gateway
, and are no longer part of public API. The changed API was not originally intended for third party use, so there should not be any major consequences from this update. These changes were implemented to remove accumulated technical debt. Refer to the com.inductiveautomation.ignition.gateway
items below for the complete list of removed API:
com.inductiveautomation.ignition.gateway.auth
- adapter
- AuthAdapter
com.inductiveautomation.ignition.gateway.config
- AbstractTypedConfig
com.inductiveautomation.ignition.gateway.http
- HttpRequest
com.inductiveautomation.ignition.gateway.mapper.attr
- user
- UserAttributeMapperConfig
- AttributeMapper
- AttributeMapperAdapter
- AttributeMapperAdapterException
- AttributeMapperConfig
- AttributeMapperException
com.inductiveautomation.ignition.gateway.security.level
- policy
- AuthenticatedDerivedSecurityLevelPolicyNode
- DerivedPolicySecurityLevelConfig
- DerivedSecurityLevelPolicy
- DerivedSecurityLevelPolicyAdapter
- DerivedSecurityLevelPolicyAdapterException
- DerivedSecurityLevelPolicyConfig
- DerivedSecurityLevelPolicyNode
- DirectSecurityLevelPolicy
- DirectSecurityLevelPolicyConfigCollection
- SecurityLevelPolicyEvaluationContext
- SecurityLevelPolicyManagerException
com.inductiveautomation.ignition.gateway.user
- UserAttribute
com.inductiveautomation.ignition.gateway.web
- attr
- AttributeSource
- AttributeSourceException
- response
- WebAuthResponseContext
- session
- WebAuthSession
- WebAuthSessionChangeEvent
- WebAuthSessionContext
- state
- WebAuthState
- strategy
- AbstractWebAuthStrategy
- WebAuthStrategy
- WebAuthStrategyAdapter
- WebAuthStrategyAdapterException
- WebAuthStrategyConfig
- WebAuthStrategyContext
- WebAuthStrategyException
- WebAuthRequestCollection
Web Refactoringβ
Web Serverβ
Java Servlet Spec will be upgraded from 4.EE8 to 6.EE10, which means all servlet APIs will have their packages renamed from javax.*
to jakarta.*
.
GSON Serializers Movedβ
The GSON serializers previously found at com.inductiveautomation.ignition.gateway.web.pages.status.serializers
and
com.inductiveautomation.ignition.gateway.web.pages.config.serializers
were moved to package com.inductiveautomation.ignition.gateway.web.serializers
.
Project Systemβ
Removed Methods:
GatewayModuleHook.initializeResourceTypeAdapterRegistry(ResourceTypeAdapterRegistry)
ResourceUtil.getValidResourceName()
Updated Methods:
- Uses of
Project
have been changed toResourceCollection
- This change also resulted in the GET request being excluded, as the methods are still functional without it, so
com.inductiveautomation.ignition.common.project.ProjectManifest.getTitle()
is nowcom.inductiveautomation.ignition.common.resourcecollection.ResourceCollectionManifest.title()
.
- This change also resulted in the GET request being excluded, as the methods are still functional without it, so
- The terminology for
Resource.getData()
remains unchanged, but it will now returnOptional<ImmutableBytes>
instead of@Nullable byte[]
. - Refactored the
ImageManager
interface to use the 8.3 resource-based configuration storage.
Designerβ
- The entire resource commit process has been made asynchronous, which guarantees the
notifyProjectSaveStart
andnotifyProjectSaveDone
methods onDesignerModuleHook
are called off the EDT. - The
abort
method on theSaveContext
delivered innotifyProjectSaveStart
has been removed. Any error during the save process are now thrown directly.
Scriptingβ
- Revamped
ScriptFunctionDocProvider
, including adding the option to return richCompletionDescriptor
objects.PropertiesFileDocProvider
has been accordingly revamped, in a backwards compatible manner. Refer to the Javadocs for PropertiesFileDocProvider for the new property keys and functionalities now available.- Some annotations were renamed in a backwards incompatible way. For example, since system libraries can now expose static fields and constants, a new annotation
@JythonElement
is used instead of@ScriptFunction
.
- Some annotations were renamed in a backwards incompatible way. For example, since system libraries can now expose static fields and constants, a new annotation
- Revamped
ScriptContext
for improved developer experience. This will affect developers creating their own scripting execution context, such as running user authored extension function style scripts, and is documented in the class.
RPCβ
The RPC mechanism that relies on Java serialization has been deprecated.
Recommended Patternβ
- Define a Java interface in common scope and annotate it with
@RpcInterface
, defining a package ID for namespacing the interface. - Implement this interface in your Gateway scope, in a regular Java class.
- Construct your interface implementation(s), and pass them to
GatewayRpcImplementation.of
to construct an automatic routing and handlingRpcDelegate
for your interfaces. - Return this constructed instance from
GatewayModuleHook.getRpcImplementation()
. - In the Designer/Client, use the static
GatewayConnection.getRpcInterface()
method to obtain a proxy instance of your interface. This proxy will automatically issue calls to the Gateway. - Use
com.inductiveautomation.ignition.common.rpc.proto.ProtoRpcSerializer.DEFAULT_INSTANCE
if you want to take advantage of Ignition's Protobuf-based serialization approach, or construct a new builder to extend it with your own GSON, Protobuf, or other sub serializers for module specific classes.
Individual callers within the Designer/Client UI should be responsible for making their calls async appropriately and handling comm or timeout exceptions, but some existing legacy methods to wrap calls still exist for backwards compatibility.
A new com.inductiveautomation.ignition.client.util.gui.progress.Task
Task class has been added, which can wrap up a function that potentially throws and either execute it blocking on the EDT while still showing progress status in a modal dialog. This should only be used for backwards compatibility. Alternatively, it can be called asynchronously on a background thread, reporting task statuses automatically to the local Designer/Client.
Push Notificationsβ
The SDK API around push notifications on the Gateway is effectively the same, but with the addition of a trailing serialization argument, where developers are now in charge of marshalling message payloads to binary over the wire. Similarly, each PushNotificationListener
must register its own deserializer capable of reading bytes off the wire and turning them back into a useful message class.
Deprecated Methods/Classesβ
Common APIβ
- Removed
SecurityUtils#decryptRSA
- Removed
SecurityUtils#getKeyParameter
,SecurityUtils#getPrivateKeyParameter
,SecurityUtils#asymmetricSign
, andSecurityUtils#generateDESedKey
Gateway APIβ
- Removed
SystemMap
,GatewayModuleHook#updateSystemMap(SystemMap)
, andRedundancyManager.getPeerSystemMap()
- Removed
GatewayContext#getLaunchManager()
- Removed the
LaunchDescriptor
class - Removed the
LaunchFlavor
class - Removed the
LaunchHandler
class - Removed the
LaunchManager
class - Removed the
SmtpManager
class, includingaccessor
on GatewayContext, and theEmailProfilerManager
class
Redundancyβ
- Removed the
RuntimeStateProvider
interface. This is replaced by theSnapshotStateProvider
interface.
Altered Routesβ
The system/projectlist
route is now split into system/launchDesigner
and system/launchVision
, where launchVision
is only available if the Vision module is installed. These new routes now return JSON.
Launchersβ
8.3 Gateways require 1.3.0+ Launchers to function. These new versions are bundled with 8.3 Gateways by default, and retain compatibility with 8.1 Gateways. Note that the DeepLinks and File Associations features introduced with the 1.3.0 launchers are not backwards compatible, but are compatible with launching against 8.1.x Gateways. Additionally, a new DLL is included with the Windows Launchers to provide an Explorer Shell Extension to support custom icons for file associations. It is optional during All User installation. Custom icons are configured under Project Properties > Launch Icon.
Workstation Onlyβ
An additional property, allow.uri.schemes
, has been added to the workstation configuration JSON. This property is an allow-list of URI schemes that will be opened by the Host OS. Schemes that should be supported by this mechanism must be in this list. It's pre-seeded with Designer, Vision, and Perspective.
Modulesβ
Perspectiveβ
EventBusβ
Ignition version 8.1.17 introduced the EventManager
class to replace uses of EventBus
. EventBus
has been completely removed with Ignition 8.3, and modules still using the EventBus
class must switch to the EventManager
implementation, which has an identical interface.
New Supported Browser Versionsβ
The basic Session functionality requirements have been updated for a variety of reasons, such as security patches, new API features, and general lack of support for older browsers. The following table displays the difference between the browser versions required by type for Ignition 8.1 and 8.3.
Browser | Minimum Version Required in 8.1 | Minimum Version Required in 8.3 |
---|---|---|
Chrome | 57 | β₯92 |
Firefox | 52 | β₯90 |
Safari | 11 | β₯15.4 |
Edge | 16 | β₯92 |
EAMβ
The following service calls have been removed.
BackupServiceβ
BackupService#requestGatewayBackup
- Replaced with
BackupService#requestGatewayBackupAsync
- Replaced with
BackupService#streamGatewayBackup
BackupService#requestModules
- Replaced with
BackupService#requestModulesAsync
- Replaced with
BackupService#restoreBackup
- Replaced with
BackupService#restoreBackupAsync
- Replaced with
InfoServiceβ
InfoService#getControllers
InfoService#getRemoteServers
SendTagsServiceβ
SendTagsService#importTags
UpgradeServiceβ
UpgradeService#triggerUpgrade
- Replaced with
UpgradeService#triggerUpgradeAsync
- Replaced with
OPC UAβ
Driver/Device APIβ
As a consequence of the platform-level ExtensionPoint
API changes, DriverType
and DeviceType
have been replaced by the new DeviceExtensionPoint
. All of the classes in the previously deprecated com.inductiveautomation.xopc.driver.api
have been removed from the public API. This includes the Driver
interface. All third party driver implementations must implement the Device
interface, which has been simplified for improved usability.
OPC Connections - Milo 1.0β
Some classes and packages from the milo-server-sdk
artifact have been relocated or renamed. Device
implementations may need to update their import statements in addition to any other changes needed to accommodate the new Device
API.
New Secrets Management APIβ
A new secrets manager has been created and added to the 8.3 codebase to provide better support for distinct secrets in the Ignition platform.
As a developer migrating code from the old PersistentRecord
API to the new Config Resource API, you might come across the problem of how to migrate secrets properly.
In general, if your old PersistentRecord
class has an EncodedStringField
property on it, then it is a secret. In your new config resource class/record, add a new field of type com.inductiveautomation.ignition.gateway.secrets.SecretConfig
. If you use the DefaultRecordEncodingDelegate
, it will know how to migrate your secret from the old EncodedStringField
to the new SecretConfig
, and there is nothing more needed as far as migration is concerned. In case you are doing some custom encoding, you can directly use the GsonAdapter
class nested in the SecretConfig
class to perform the Gson encoding/decoding of SecretConfigs
yourself.
Note that when your system loads from the new resource API, secrets are no longer considered static. This is because secrets may be referenced from a secret provider. The intention is to load the secret on demand.
String getPassword(gatewayContext context, MyConfigResource resource) throws Exception {
SecretConfig secretConfig = resource.getPassword();
Secret<?> secret = Secret.create(gatewayContext, secretConfig);
Plaintext plaintext = secret.getPlaintext();
String password;
try {
return plaintext.getAsString(StandardCharsets.UTF_8);
} finally {
// password is kept around as a String anyway, but might as well clear the bytes
// held by the Plaintext instance...
plaintext.clear();
}
}
You can hold onto your Secret instance as long as your config resource has not changed. You can repeatedly call getPlaintext()
to get the latest value of the secret on demand.
It is best to keep the secret in the form of a byte array or char array, and to βclearβ the array with zeros or spaces when done. This helps to reduce the amount of time the plaintext secret value is in memory, which reduces the likelihood of the plaintext value leaking somehow through memory analysis.
However, if you must convert to a String due to the API only accepting secrets as Strings, clearing the Plaintext instance after grabbing the value as a String means youβll have to rely on the garbage collector reclaiming the String when no longer used.