1. Introduction

This document describes the changes in the SDK design between version 4.x and 5.0.0. You can use this document to help you to migrate your applications built with SDK 4.x to use the new SDK version 5.0.0 (plus some notes for 5.x.0). If your application is using older than 4.x, please see the other migration guides before reading this.

2. Java version

SDK 5.x for the first time in SDK history bumps the minimum required Java version to 8. Java 8 was already required in 4.x PubSub editions, but now it is needed for every edition.

Android API level minimum is expected to be 26, but this depends on desugaring options. If you encounter a problem, let us know.

In 5.1.0 the following classes related to modelling a "Browse Path" were changed. This mostly affects API related to the UaNodeBuilderConfiguration(s) for NodeManagerUaNode.createInstance, NodeBuilder (and some internal systems):

  • com.prosysopc.ua.UaBrowsePathcom.prosysopc.ua.UaBrowseNamePath

  • com.prosysopc.ua.UaRelativePathcom.prosysopc.ua.UaRelativeNamePath

  • com.prosysopc.ua.server.BrowsePathcom.prosysopc.ua.RelativeNamePath

  • New class com.prosysopc.ua.BrowseNamePath was added.

The semantic of the classes are a starting node (in UaBrowseNamePath+BrowseNamePath) and a path of BrowseNames (of nodes).

There are now new classes com.prosysopc.ua.UaBrowsePath and com.prosysopc.ua.UaRelativePath with additional semantic, they now are equivalent to com.prosysopc.ua.stack.core.BrowsePath and com.prosysopc.ua.stack.core.BrowsePath. Also a UaRelativePathElement was also added to be the counterpart of com.prosysopc.ua.stack.core.RelativePathElement. These UaXXX variations do not use NamespaceIndex-based classes, i.e. they use UaNodeId in place of NodeId, UaQualifiedName instead of QualifiedName and so on where namespace is represented with UaNamespace (i.e. the URI-form).

4. Old serialization system removed

The old Serializers based serialization system is removed. Now everything works based on UaDataTypeSpecification. Also, IEncoder/IDecoder implementations such as BinaryEncoder no longer "keys" on Java Classes, but instead the API is based on UaNodeId as the DataTypeId, which is then used to find respective UaDataTypeSpecification. This mainly affects Code Generator outputs, but might be relevant if you have used these manually.

StructureSpecification is now interface, but has the same static factory method for obtaining a Builder. This was made so OptionSetStructure can multiple inherit StructureSpecification and OptionSetSpecification. FieldSpecification is now an interface as well and directly implemented by the .Fields enum of generated Structures. As a result, there is no longer the option to use .equals for them.

5. OptionSets

OptionSet types now have a nested .Options enumeration instead of .Fields. AccessLevelType is an OptionSet, thus types like that are affected, if you have used the options (4.x fields) directly. In addition using the Options when constructing the values is the recommended way.

Also there is now UaDataTypeSpecification for OptionSets: OptionSetSpecification (for UInteger-based) and OptionSetStructureSpecification(for OptionSet-Structure based).

6. Localization improvements

LocalizedTextMap is removed. LocalizedText now handles all localized values within the same Java object. These multi-locale values can be obtained via LocalizedText.builder(). Most of the API previously in LocalizedTextMap is now part of LocalizedText. Note that on the client side LocalizedText always holds only a single localized value based on the locale of the Session. Thus this mostly helps only the server side. The decision to use LocalizedText in this way allows e.g. Structure fields that could be localized to keep the old type and allow Codegen UaNode classes to also support multi-locale values with existing API.

7. Code Generator

The Codegen configuration is the same as in 4.x, but a new feature was added that by default splits the output packages per NodeClass. This can be turned off to retain the previous package structure. For more information, check the Codegen manual.

The outputs of the Codegen have changed. SDK no longer has the "serialization system" regarding Structure(s), everything internally now works per StructureSpecification. Also the serialization process itself keys now on DataType UaNodeIds instead of Java classes. This allowed us to fix some issues since it was complicated as the DynamicStructure.class mapping had to be changed constantly when encoding and decoding custom Structures.

The constructor of generated UaNode classes is changed in 5.x: now the constructor just takes an UaNode.Parameters instance. If you have manually edited XXXTypeNode and XXXTypeImpl outputs you must change the constructor.

There are some new outputs as well. Now a UaIds equivalent to Ids is generated. UaIds contains the same identifiers, but as UaNodeId, which are used for some of the newer APIs of the SDK.

Also, now a CommonInformationModel is generated. This holds references to all generated UaDataTypeSpecification(s). It is automatically registered if client/server side information model output is registered, which also happens automatically (already in 4.x) assuming the client_model_provider and/or ` server_model_provider has been used so SDK can automatically find the classes via Java ServiceLoader.

8. Reflection changes

SDK now uses less Reflection. It is not completely eliminated however. SDK also no longer uses setAccessible(true) or isAccessible() (see also), as it could cause issues on newer Java versions. However, this has the potential to break some existing code. If that happens contact support.

9. Changes in toString for some types

ExpandedNodeId, UaNodeId and UaQualifiedName toString contains changes.

ExpandedNodeId.toString format now only escapes % and ; characters for the namespace uri component. Previously it was based on java.net.URLEncoder.encode(namespaceUri, "ISO8859-1"). The output format itself has not changed and is based on the The XML encoding format. If you have persisted toString values, you might need to decode them manually based on URLDecoder.decode(ns, "ISO8859-1") for the namespaceUri part. Loading them with 5.x without this will result in a different namespace uri than was originally encoded.

UaNodeId.toString is now same as uaNodeId.asExpandedNodeId().toString(), with the above changes to the ExpandedNodeId. Previously the format was "namespaceuri:valuepart" and not intended for parsing purposes.

UaQualifiedName.toString now uses a format "nsu=namespaceuri;name=namepart". This is similar to the ExpandedNodeId format, but is a custom format i.e. OPC UA doesn’t have a "uri-version" for QualifiedName. The namespaceUri is escaped similar to the ExpandedNodeId changes above.

UaNodeId and UaQualifiedName both now have a new parse(String) version (compared to the parse(namespace, valuepart)) that takes in the single String that was the output of toString. The previous toString output was not inteded for parsing, this new one is. This changes these values when used in persisted PubSub configuration.

10. PubSub

PubSubEvents is now PubSubSystemEvents to put emphasis that they are events of the PubSubSystem, not OPC UA PubSub "Events". PubSubSystemEvents has some new events and some of the functionality was changed. PUB_SUB_JSON_DATASET_MESSAGE_RECEIVED and PUB_SUB_UADP_DATASET_MESSAGE_RECEIVED are now done Reader-level (compared to Group level in 4.x). PUB_SUB_UADP_NETWORK_MESSAGE_RECEIVED, PUB_SUB_MQTT_UADP_NETWORK_MESSAGE_RECEIVED and PUB_SUB_MQTT_JSON_NETWORK_MESSAGE_RECEIVED can be used to see connection-level messages.

Additionally due to UaNodeId and UaQualifiedName toString format change (see release notes or above) and addition of a single-String parse the configuration outputs (from com.prosysopc.ua.samples.pubsub.SamplePubSubConfiguration.save(File, PubSubSystemConf, EncoderContext), that uses com.prosysopc.ua.pubsub.PubSubConf.toMap(MapKind<T>)) are different. The PubSubConf.Builder.setAll(MapKind<S>, S) (thus com.prosysopc.ua.samples.pubsub.SamplePubSubConfiguration.load(File, EncoderContext)) accepts both 4.x and the new format.

11. Samples

Samples no longer use a private key password. This was decided to be better than a hardcoded password 'opcua', since basically it is the same thing. Added comment to the code, but also explaining here: A real application should be able to use 3rd-party generated certificates (i.e. certs generated not by SDK itself). This means that either they must be made without a password, using the hardcoded password or the application must be able to receive the password from the user.

If you try to load the old certificate files with the new sample code the loading will fail. Thus you must either delete the old files so SDK re-creates them or keep the old code that used the password. Note that this change is only related to the sample code itself, the old code using the password will work with 5.0.0.

SampleConsoleServer no longer by default starts an opc.https endpoint. The idea is that this confuses new users less as they seemed to be "on the same level", but in reality opc.https is not supported well nor used. It can be enabled with a flag.