Prosys OPC UA Java SDK Client Tutorial
Prosys OPC UA Java SDK Client Tutorial
Welcome to the Prosys OPC UA Java SDK Tutorial for Client software development. With this
quick introduction you should be able to grab the basic ideas behind the Java UA SDK.
Note that this Tutorial assumes that you are already familiar with the basic concepts of the OPC
UA communications, although you can get to the beginning without much prior knowledge.
For a full reference on OPC UA communications, we recommend (Mahnke, Leitner, Damm: OPC
Unified Architecture, Springer-Verlag, 2009, ISBN 978-3-540-68898-3).
Contents
1. Installation ..................................................................................................................................................... 4
2. Sample applications ....................................................................................................................................... 4
3. UaClient object .............................................................................................................................................. 4
4. Server connection .......................................................................................................................................... 4
5. Security settings ............................................................................................................................................ 5
5.1 Application Identity ................................................................................................................................. 5
5.1.1 Application Description .................................................................................................................... 5
5.1.2 Application Certificate ...................................................................................................................... 5
5.1.3 Issuer Certificate ............................................................................................................................... 6
5.1.4 Multiple Application Instance Certificates ....................................................................................... 6
5.1.5 HTTPS Certificate .............................................................................................................................. 7
5.1.6 Application Identity .......................................................................................................................... 7
5.2 Security Modes ........................................................................................................................................ 7
5.2.1 SecurityMode for UA Binary ............................................................................................................. 7
5.2.2 HTTPSSecurityPolicy ......................................................................................................................... 8
5.3 User Identity ............................................................................................................................................ 8
5.4 Validating Server Certificates .................................................................................................................. 8
5.5 Teach Yourself the Security Details ......................................................................................................... 9
6. Connect / Disconnect .................................................................................................................................... 9
6.1 Connection Monitoring ......................................................................................................................... 10
6.1.1 ServiceException............................................................................................................................. 10
6.1.2 Timeout........................................................................................................................................... 10
6.1.3 Server Status monitoring ................................................................................................................ 10
(1) Automatic reconnect ................................................................................................................... 11
7. Browse the address space ........................................................................................................................... 11
7.1 Browsing through the nodes ................................................................................................................. 11
8. Read values .................................................................................................................................................. 12
9. Write values ................................................................................................................................................. 12
10. Subscribe to data changes ......................................................................................................................... 12
11. Subscribe to events ................................................................................................................................... 13
12. History Access ............................................................................................................................................ 15
12.1 Reading history .................................................................................................................................... 15
12.2 Updating or deleting history................................................................................................................ 15
1. Installation
See the installation instructions in README.txt (and at the download site). There are also notes
about the usage and deployment of external libraries used by the SDK.
2. Sample applications
The SDK contains a sample client application, SampleConsoleClient. This tutorial will refer to that
code while explaining the different steps to take in order to accomplish the main tasks of an OPC
UA client.
3. UaClient object
The UaClient class is the main class you will be working with. It encapsulates the connection to the
OPC UA server and handles the various details in the actual OPC UA communications, providing
you a simple interface to access from your applications. These are the lines in the
SampleConsoleClient.java that create the UaClient:
4. Server connection
The serverUri argument, in the previous example, defines the server you are connecting to.
Some sample URIs are
URI Server
opc.tcp://<hostname>:52520/OPCUA/SampleConsoleServer Prosys OPC UA Java SDK
Sample Console Server
https://<hostname>:52443/OPCUA/SampleConsoleServer Prosys OPC UA Java SDK
Sample Console Server
opc.tcp://<hostname>:53530/OPCUA/SimulationServer Prosys OPC UA Simulation
Server
https://<hostname>:53443/OPCUA/SimulationServer Prosys OPC UA Simulation
Server
opc.tcp://<hostname>:4841 Unified Automation
Demo Server
opc.tcp://<hostname>:62541/Quickstarts/DataAccessServer OPC Foundation QuickStart
Data Access Server
where <hostname> is the host name of the computer in which the server is running.1
You need to define the complete URI either in the constructor or with the setUri() method. These
throw a UriSyntaxException if the given URI is not valid. In case you want to validate the URI
before giving it, you can use a UaAddress instance as a constructor parameter or with
setAddress().
The first part of the URI defines the transport protocol to use. opc.tcp refers to UA Binary
communication which is usually the preferred protocol. https is an alternative protocol defined in
OPC UA 1.02 specification. All applications do not necessarily support HTTPS. Some
1
The servers define a list of endpoints that they are listening to. The actual hostname in the endpoint may differ from
the one that you use for connection.
For Windows hostname resolution, see http://technet.microsoft.com/en-us/library/bb727005.aspx. If you are using
the client in Linux, you cannot use NetBIOS computer names to access Windows servers. In general it is best to use
TCP/IP DNS names from all clients. Alternatively, you can always use the IP address of the computer.
(especially .NET applications) may also support the http protocol, which in practice means a
SOAP protocol based transport (whereas https means UA Binary over a secure HTTP
connection).
5. Security settings
OPC UA applications enable full security, integrated in the communications. In the client, you can
decide, which kind of security settings you want to use in your connections.
All OPC UA applications must also define some characteristics of themselves. This information is
communicated to other applications via the OPC UA protocol, when the applications are connected.
ProductUri, on the other hand, is used to identify your product and should therefore be the same
for all instances. It should refer to your own domain, for example, to ensure that it is globally unique.
The URIs must be valid identifiers, i.e. they must begin with a scheme, such as urn: and may not
contain any space characters. There are some applications in the market, which use invalid URIs
and may therefore cause some errors or warning with your application.
2
If your application does not use security (see 5.2), you may also create the identity without any certificate, using the
default constructor. However, you should always set the ApplicationDescription to the identity.
The fourth parameter in loadOrCreateCertificate simply defines the path where the certificate
files are stored. Do not mind about it at the moment: it is clarified later
The last parameter enables automatic certification renewal, when it gets outdated.
If you wish to create your own issuerKey in your application, you can do that with the Java SDK
like this:
KeyPair issuerCertificate =
ApplicationIdentity.loadOrCreateIssuerCertificate(
"ProsysSampleCA", privatePath, "opcua", 3650, false);
which creates a certificate key pair with a private key password (opcua) for ProsysSampleCA
for 10 years (3650 days). The key pair is stored in the privatePath (which referes to the PKI
directory of the validator, as above).
The self-made issuer key does not replace a real CA. The HTTPS may require a CA signed
certificate (espscially with the .NET applications), and therefore it may be necessary to create your
own CA key. You will need to provide the CA key to the other applications, so that they can verify
the application instance certificates.
The SDK enables usage of several certificates by defining an array of keySizes, e.g.:
// Use 0 to use the default keySize and default file names (for other
// values the file names will include the key size.
int[] keySizes = new int[] { 0, 4096 };
The identity is then initialized as
3
Note that if some other application gets the same key pair, it can pretend to be the same client application. The
private key should be kept safe, in order to reliably verify the identity of this application. Additionally, you may secure
the usage of the private key with a password, required to open it for use (but you need to add that in clear text in your
application code, or prompt it from the user). The certificate is public and can be distributed and stored freely in the
servers and anywhere else. Note: The SDK stores private keys in .pem format, which supports password protection. If
you get the certificate and private key from an external CA, you may get a .pfx file: if such is present (and .pem is not
present), the application will use it.
client.setApplicationIdentity(identity);
In addition, you can add Software Certificates that your application has received from the OPC UA
certification process4 to the ApplicationIdentity. These are used to validate your applications
conformance to the OPC UA protocol, to the server applications it is communicating with.
client.setSecurityMode(SecurityMode.BASIC128RSA15_SIGN_ENCRYPT);
This is the default setting, providing full encryption between all communications. It will, of course,
affect the performance of the communications a little bit, but in general, you had better use secure
communications, unless you have a good reason to omit it. If you decide so, you can disable
security with
client.setSecurityMode(SecurityMode.NONE);
There are also several other alternatives. You can use SecurityMode.BASIC128RSA15_SIGN to
sign all communication messages, but leave them unencrypted. The server may also support other
security standards and levels, in which case you can define a custom SecurityMode. To find out
which security modes are supported by the server, call
client.getSupportedSecurityModes();
To use 256-bit security, you will need to install the JCE Unlimited Strength Jurisdiction Policy Files
into the JRE. Look for those from the Oracle and follow the instructions on how to install them.
4
OPC Certification Process Web site, http://www.opcfoundation.org/Certification.aspx. The software certificates have
not been defined yet, and are a future feature, though.
5.2.2 HTTPSSecurityPolicy
If you use the HTTPS protocol for server communication the UaClient will negotiate a usable TLS
security policy with the server application. You can define which policies your application supports
with
client.getHttpsSettings().setHttpsSecurityPolicies(HttpsSecurityPolicies.AL
L);
The default policies (included in ALL) are TLS 1.0 and TLS 1.1 (there is a problem with the current
JRE 7 & 8, which makes TLS 1.2 not to work with the Java stack).
The CertificateValidator and HttpsHostnameVerifier provide an option to verify the server certificate.
The latter is just defining if a standard validation is done against the host name of the server. By
default, no checking is made, but you can define stricter rules with, for example these
client.getHttpsSettings().setHttpsCertificateValidator(yourValidator);
client.getHttpsSettings().setHttpsHostnameVerifier(org.apache.http.conn.ssl
.SSLSocketFactory.STRICT_HOSTNAME_VERIFIER);
NOTE: If you use HTTPS, UA security is not used, which means that SecurityMode.NONE is
always used for the SecurityMode.
client.getSupportedUserIdentityTokens();
To validate the certificate of the OPC UA servers, you can define a CertificateValidator in
UaClient. This validator, if assigned, is automatically used to validate the certificates received from
the server.
Now, to provide a standard certificate validation mechanism that can be used to define certain
certificates as trusted, the SDK contains a specific implementation of the CertificateValidator,
the PkiFileBasedCertificateValidator. You can create the validator as follows:
PKI\
CA\
certs\
rejected\
The trusted certificates are stored in the certs-directory and the untrusted in rejected. By default,
the certificates are not trusted so they are stored in rejected. You can then manually move the
trusted certificates to the certs directory.
Additionally, you can plug a custom handler to the Validator by defining the ValidationListener:
validator.setValidationListener(validationListener);
@Override
public ValidationResult onValidate(Cert certificate,
ApplicationDescription applicationDescription,
EnumSet<CertificateCheck> passedChecks) {
// Called whenever the PkiFileBasedCertificateValidator has
// validated a certificate
[...]
}
The SampleConsoleClient uses this method to prompt the user whether to accept the server
certificate when connecting for the first time. The user can accept the certificate permanently, just
once or reject it. In the first case the certificate is placed in the certs directory automatically, and
in the latter cases it is placed in the rejected directory. In the last case, connection to the server is
cancelled, due to the certificate problem.
You are of course free to use the listener to define any custom logic, but in principle, you should
only trust certificates for which passedChecks equals CertificateCheck.COMPULSORY. Normally
you can trust self-signed certificates, so that check is not included in the COMPULSORY definition.
Most OPC UA certificates will probably be self-signed, because they are easy to generate
automatically. A proper Certificate Authority should be preferred in real systems to enable a
properly managed system for certificate management.
Read the OPC UA book for more details on the OPC UA security settings and how they should be
applied. The security technology follows standard PKI (Public Key Infrastructure) principles, so all
material related to that can also be used to understand the basics.
Also try different settings in different environments so that you know more than guess.
6. Connect / Disconnect
Once you have managed to get over the first, compulsory hurdles of defining where and how to
connect, you can simply connect to the server with
client.connect();
If that fails, you will get an exception. If the actual connection cannot be made, you will get a
ServerConnectionException. If you get a connection, but something goes wrong in the server,
the UaClient typically throws a ServiceException. You may also see a ServiceFaultException,
ServiceResultException or some other runtime exception, which are thrown from the actual UA
stack5.
Once you have the connection, you can start playing with the server. In the SampleConsoleClient
you are taken to a menu where you can pick up the tasks you want to try to.
client.disconnect();
6.1.1 ServiceException
The service calls (described in the following sections) raise ServiceException in case of
communication or other service errors.
6.1.2 Timeout
The Java stack handles temporary communication errors by retrying to establish a lost connection
in certain cases. It also takes care of timeout handling, i.e. the synchronous service calls are
monitored for a response until the timeout delay occurs without a response. You can define the
default timeout (ms) to use in the UaClient:
client.setTimeout(30000);
You can listen to changes in the status by defining your own ServerStatusListener, for example
as follows:
@Override
public void onStateChange(UaClient uaClient, ServerState oldState,
ServerState newState) {
// Called whenever the server state changes
printf("ServerState changed from %s to %s\n", oldState, newState);
if (newState.equals(ServerState.Unknown))
println("ServerStatusError: " +
uaClient.getServerStatusError());
}
@Override
5
Often the original exception from the stack is also available as the Cause from the ServiceException.
In the UaClient, the address space is accessed through the you guessed it AddressSpace
property! You can call browse to request nodes from the server. You start from the RootFolder
(to which the nodeId is initialized to) and follow references between the nodes. There may be a
huge number of references from a node, so you can define some limitations on what kind of results
you wish from the server. You can set these with the different properties of the AddressSpace, e.g.:
client.getAddressSpace().setMaxReferencesPerNode(1000);
client.getAddressSpace().setReferenceTypeId(
Identifiers.HierarchicalReferences);
by which you define a limit of 1000 references per call to the server6 and that you only wish to
receive the hierarchical references between the nodes.
6
although the AdressSpace will use this internally, while communicating with the server, and may provide you all the
nodes the server has.
8. Read values
Once you have a node selected, you can read the attributes of the node. There are actually several
alternative read-calls that you can make in the UaClient. In SampleConsoleClient we use the basic
In general, you should avoid calling the read methods for individual items. If you need to read
several items at the same time, you should consider using client.read(). It is a bit more
complicated to use, but it will only make a single call to the server to read any number of attributes.
Or if you really want to monitor variables that are changing in the server, you had better use the
subscriptions, as described below.
9. Write values
Similar to reading, you can also write values to the server. For example:
If the operation fails, you will get an exception. For service call errors, such that the server could
not handle the service request at all, you can expect ServiceExceptions. For an individual
operation that fails, you will get a StatusException. An example of the latter one is a failing write
operation, when you try to change a value whose access rights do not permit the change.
If you perform several operations at a single call, you can only expect a ServiceException. For
each operation you will get a StatusCode, which indicate which individual operations succeeded
and which failed. Use StatusCode.isBad() and .isGood() to check whether the operation failed
or not. The StatusCode provides a complete code, which you can check against known errors in
StatusCodes. In case of failure, you may also get additional information in a DiagnosticInfo
structure. These fields are present in the exceptions. You can also examine the result codes of the
last service call from client.getLastServiceDiagnostics() and
getLastOperationDiagnostics().
In the client, you can then just listen to the change notifications, which the server is instructed to
send when the item values change according to the subscription properties:
item.setDataChangeListener(dataChangeListener);
The listener is defined as follows:
You may also wish to listen to the alive and timeout events in the subscription. These will help you
to monitor that the server is actively monitoring the values, even when they are not actually
changing so that new data change notifications would be sent.
subscription.addAliveListener(new SubscriptionAliveListener() {
@Override
public void onAlive(Subscription s) {
// the server acknowledged that the connection is alive,
// although there were no changes to send
}
@Override
public void onTimeout(Subscription s) {
// the server did not acknowledged that the connection is alive,
// and the maxKeepAliveCount has been exceeded
}
});
7
The current version of the client is actually adding two custom fields in eventFieldNames as well. These are initialized
to null and created at run-time, because the QualifiedName-identifiers need a namespaceIndex which depends on the
dynamic index in the server. See the code sample for details in initEventFieldNames().
And finally we are ready to create the event item, using the noedId and filter:
The createBrowsePath() method is special to the sample. It breaks the QualifiedNames, which have / delimiters to a
browse path, i.e. an array of QualifiedNames.
HistoryData d = result[0].getHistoryData().decode();
DataValue[] values = d.getDataValues();
What you need to be aware of is that there are several methods that the historyRead actually
supports, depending on which HistoryReadDetails you use. For example, in the above example
we used ReadRawModifiedDetails, to read a raw history (the same structure is used to read
Modified history as well, therefore the name).
To make your life a bit easier, UaClient also defines several convenience methods to make specific
history requests. For example, the above can also be performed with
List<ReferenceDescription> methodRefs =
client.getAddressSpace().browseMethods(nodeId);
to get a list of the method references from the node.
The UaMethod is initialized with the InputArguments and OutputArguments properties, which you
can examine for the argument name, type, etc.
Note also that you will usually need to use the DataTypeConverter to convert the
inputArguments to the correct data type, before calling the method. The OPC UA specification
defines that the server may not convert the arguments, if they are provided in incorrect data types.
So you will get Bad_InvalidArgument errors for them. See the sample code
(SampleConsoleClient.readInputArguments()) for more details.
You can access these from the AddressSpace. To register a Node for quick access, call:
You can simply request the node objects from the address space using the methods getNode(),
getType(), getMethods(), etc.
To see it in action, just go and explore the sample code in more detail especially the methods,
printCurrentNode() and referenceToString().
In SDK 2.0, getNode() has become even more useful. If you register generated classes, you can
use complete UA types in your application through the respective Java classes. Read on to learn
more about that.
To initially setup your code generation infrastructure, you have to edit the codegen.properties file: