Prosys OPC UA Java SDK 2.0 Release: Using Code Generated Classes
We released version 2.0 of our OPC UA Java SDK earlier this week.
- OPC Foundation Java Stack 1.02
- HTTPS protocol
- New SecurityPolicy: Basic256Sha256
- More flexible security library usage (Bouncy Castle/Spongy Castle(for Android)/Sun JCE)
- Standard OPC UA types as (generated) Java classes both on the client and server side
- Option to use types for companion specifications (DI, ADI, PLCopen)
- Code generator for enabling usage of custom types, both on the server and client side
- Support for OPC UA File Transfer (FileType)
- Enables disabling SecurityMode.None in the server
- Enables disabling the internal discovery server
- Enables binding the server to network interfaces independent of the EndpointUrls
OPC UA 1.02 features are explained in a previous blog post.
Full release notes can be found here. The focus of this blog post is on using the code generated classes because it is now the only way to create standard UA types in the server and they can also be used in the client side to make working with the nodes easier. It is also the main reason why the release took so long. Converting the SDK to use code-generated classes internally was not easy, but it also serverd as a quick feedback loop to improve the code-generator to produce classes that are good enough to be useful.
Code generation is a major new feature in 2.0. Some of this has been shown in a previous blog post. The generator generates 5 class files for a given UA type: 1 interface and 4 classes. They are named the following way:
xxxType, interface, e.g. AnalogItemType
xxxTypeImplBase, client side base implementation of the interface (abstract class)
xxxTypeNodeBase, server side abstract base implementation (abstract class)
xxxTypeImpl, client side actual implementation
xxxTypeNode, server side actual implementation, implementation of UA methods
Idea is that the interface and the Base classes are always generated (e.g. they do not go to version control systems) and the Impl and Node classes can contain hand-written code, e.g. the implementations of UA methods and any convenience methods. The classes have same hierarchy as in the UA types. The standard types can be found in the following packages:
The SDK also has classes for companion specifications (DI, ADI, PLCopen), they can be found in similar packages (replace
plc). Note however that these classes are just code-generated, therefore e.g. DI classes do not have any UA method implementations.
Using code generated classes on the client side
On the client side the interface should be used, because the SDK client-side implementations do not add any convenience methods to the interface. The
AddressSpace.getNode(NodeId) method has been overloaded with one taking a
Class parameter. Therefore you can now call:
AnalogItemType node = client.getAddressSpace().getNode(NodeId, AnalogItemType.class);
You can then use the node to get it’s properties:
//returns the InstrumentRange UaProperty UaProperty property = node.getInstrumentRangeNode(); //direct return for the value of the InstrumentRange Property Range instrumentRange = node.getInstrumentRange();
In the above example, the
getInstrumentRangeNode() can return
null, if the server side Node does not have an InstrumentRange Property. This can happen because the InstrumentRange is an Optional Property in the UA Specification. The methods in the generated classes have an
@Optional annotation, if the Node is defined as Optional. They can also have a
@Mandatory annotation indicating that the return value should not be null (but it can be
null if the server does not follow the UA Specification). The value returned by
getInstrumentRange can be
null, firstly if the InstrumentRange Node does not exist and secondly if the actual value is
The Client side nodes do have a property value setter method similar to getter, but it should be noted here that that is for SDK’s internal use, i.e. calling the setter will not write the value to the server. Writing values must still be done using UaClient.write() methods.
Using code generated classes on server side
The SDK uses now the code-generated classes internally. The old standard type nodes from package
com.prosysopc.ua.server.nodes.opcua are removed because they are not directly compatible: some interfaces are now supporting code-generated nodes and they can only support one class a time.
On the server side it is better to use the actual implementation class, `xxxTypeNode’, because some operations shouldn’t fail on the server side. Therefore methods in the actual implementation do not throw ServiceException and setting values do not throw StatusExceptions. Also the classes do have some convenience methods.
The most visible change is that the generated classes cannot be instantiated directly. This is because each generated class knows only one step of their structure and the Nodes do not store their own structure. Therefore the generated nodes must be instantiated using a
NodeBuilder or using
NodeManagerUaNode.createInstance(...) (which uses a
NodeBuilder internally). The following lines show an examples of instantiating an
// 1 AnalogItemType node = nodeManagerUaNode.createInstance( AnalogItemType.class, "AnalogItem"); // 2 AnalogItemTypeNode node = nodeManagerUaNode.createInstance( AnalogItemTypeNode.class, nodeId, browseName, displayName); // 3 NodeBuilder<AnalogItemType> nb = nodeManagerUaNode.createNodeBuilder(AnalogItemType.class); AnalogItemType node = nb.setNodeId(...) .setBrowseName(...) .setDisplayName(...) .build();
In each of those examples, the new
AnalogItemType node is also added to the
The default instantiation of generated classed do not instantiate Optional InstanceDeclarations (UaObject/UaVariable instances in type definitions). This means that, for example,
AnalogItemType by default does not have an InstrumentRange Property. These can be configured using
UaNodeBuilderConfiguration, which is an interface for configuring a
NodeBuilder. The SDK has one implementation,
NodeBuilderConfiguration, which enables defining which Optionals to instantiate using
BrowsePaths. In addition to defining which Optionals to instantiate, the
UaNodeBuilderConfiguration also defines how exactly the nodes should be instantiated. More on that subject on a later blog post. The following example explains how to use the
NodeBuilderConfiguration (from our SampleConsoleServer):
// Configure the optional nodes using a NodeBuilderConfiguration NodeBuilderConfiguration conf = new NodeBuilderConfiguration(); // You can use NodeIds to define Optional nodes (good for standard UA // nodes as they always have namespace index of 0) conf.addOptional(Identifiers.AnalogItemType_EngineeringUnits); // You can also use ExpandedNodeIds with NamespaceUris if you don't know // the namespace index. conf.addOptional(new ExpandedNodeId(NamespaceTable.OPCUA_NAMESPACE, Identifiers.AnalogItemType_InstrumentRange.getValue())); // You can also use the BrowsePath from the type if you like (the type's // BrowseName is not included in the path, so this configuration will // apply to any type which has the same path) // You can use Strings for 0 namespace index, QualifiedNames for 1-step // paths and BrowsePaths for full paths // Each type interface has constants for it's structure (1-step deep) conf.addOptional(AnalogItemType.DEFINITION); // Use the NodeBuilder to create the node final AnalogItemType node = complianceNodeManager .createNodeBuilder(AnalogItemType.class, conf) .setName(dataTypeName + "AnalogItem").build();
The code-generation and generated standard UA types are a major feature in 2.0. On the client side it allows easier access to sub-structures of a node of known type. On the server side it changes how the nodes are instantiated manually but opens up options in configuring how the nodes are instantiated. The instantiation process is quite complex and is one reason why the 2.0 release took so long.
Expertise and responsibility areas: OPC UA product development and project work
Prosys is a leading provider of professional OPC software and services with over 10 years of experience in the field. OPC and OPC UA (Unified Architecture) are communications standards used especially by industrial and high-tech companies.
Newest blog posts
Importing Information Models from OPC UA NodeSet files with Prosys OPC UA SDK for Java and Prosys OPC UA Simulation Server
Using our Prosys OPC UA SDK for Java to gather historical data.
Security vulnerability in the OPC UA Java Stack.