Apache Camel 2.19.0 is close to is release and the OPC UA component called “camel-milo” will be part of it. This is my Eclipse Milo backed component which was previously hosted in my personal GitHub repository ctron/de.dentrassi.camel.milo. It now got accepted into Apache Camel and will be part of the 2.19.0 release. As there are already a release candidates available, I think it is a great time to give a short introduction.
In a nutshell OPC UA is an industrial IoT communication protocol for acquiring telemetry data and command and control of industrial grade automation systems. It is also known as IEC 62541.
The Camel Milo component offers both an OPC UA client (milo-client
) and server (milo-server
) endpoint.
Running an OPC UA server
The following Camel example is based on Camel Blueprint and provides some random data over OPC UA, acting as a server:

The blueprint configuration would be:
<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.osgi.org/xmlns/blueprint/v1.0.0 https://osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
http://camel.apache.org/schema/blueprint https://camel.apache.org/schema/blueprint/camel-blueprint.xsd
">
<bean id="milo-server"
class="org.apache.camel.component.milo.server.MiloServerComponent">
<property name="enableAnonymousAuthentication" value="true" />
</bean>
<camelContext xmlns="http://camel.apache.org/schema/blueprint">
<route>
<from uri="timer:test" />
<setBody>
<simple>random(0,100)</simple>
</setBody>
<to uri="milo-server:test-item" />
</route>
</camelContext>
</blueprint>
And adding the following Maven build configuration:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>de.dentrassi.camel.milo</groupId>
<artifactId>example1</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>bundle</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<camel.version>2.19.0</camel.version>
</properties>
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.1</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-core-osgi</artifactId>
<version>${camel.version}</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-milo</artifactId>
<version>${camel.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>3.3.0</version>
<extensions>true</extensions>
</plugin>
<plugin>
<groupId>org.apache.camel</groupId>
<artifactId>camel-maven-plugin</artifactId>
<version>${camel.version}</version>
</plugin>
</plugins>
</build>
</project>
This allows you to simply run the OPC UA server with:
mvn package camel:run
Afterwards you can connect with the OPC UA client of your choice and subscribe to the item test-item
, receiving that random number.
Release candidate
As this is currently the release candidate of Camel 2.19.0, it is necessary to add the release candidate Maven repository to the pom.xml
. I did omit
this in the example above, as this will no longer be necessary when Camel 2.19.0 is released:
<repositories>
<repository>
<id>camel</id>
<url>https://repository.apache.org/content/repositories/orgapachecamel-1073/</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>camel</id>
<url>https://repository.apache.org/content/repositories/orgapachecamel-1073/</url>
</pluginRepository>
</pluginRepositories>
It may also be that the URLs (marked above) will change as a new release candidate gets built. In this case it is necessary that you update the URLs to the appropriate
repository URL.
What’s next?
Once Camel 2.19.0 is released, I will also mark my old, personal GitHub repository as deprecated and point people towards this new component.
And of course I am happy to get some feedback and suggestions.
6 thoughts on “OPC UA with Apache Camel”
Hi Jens,
I tried the above while also using a milo-client endpoint to test communication but I never receive anything on the client. Am I doing something wrong?
Routes below:
hello ${random(0,100)}
Logs:
15:00:03.833 INFO {main} [o.e.m.opcua.sdk.server.NamespaceManager] : added namespace index=0, uri=http://opcfoundation.org/UA/
15:00:03.843 INFO {main} [o.e.m.opcua.sdk.server.NamespaceManager] : registered and added namespace index=1, uri=urn:org:apache:camel:milo:server
15:00:04.053 INFO {main} [o.e.milo.opcua.sdk.server.OpcUaServer] : Binding endpoint opc.tcp://srinivaska-laptop:12685 to 0.0.0.0 [None/None]
15:00:04.053 INFO {main} [o.e.milo.opcua.sdk.server.OpcUaServer] : Binding endpoint opc.tcp://srinivaska-laptop.cybage.com:12685 to 0.0.0.0 [None/None]
15:00:04.053 INFO {main} [o.e.milo.opcua.sdk.server.OpcUaServer] : Binding endpoint opc.tcp://192.168.56.1:12685 to 0.0.0.0 [None/None]
15:00:04.053 INFO {main} [o.e.milo.opcua.sdk.server.OpcUaServer] : Binding endpoint opc.tcp://172.27.56.191:12685 to 0.0.0.0 [None/None]
15:00:04.053 INFO {main} [o.e.milo.opcua.sdk.server.OpcUaServer] : Binding endpoint opc.tcp://127.0.0.1:12685 to 0.0.0.0 [None/None]
15:00:04.083 INFO {main} [o.e.milo.opcua.sdk.server.OpcUaServer] : eclipse milo opc-ua stack version: 0.1.0
15:00:04.083 INFO {main} [o.e.milo.opcua.sdk.server.OpcUaServer] : eclipse milo opc-ua sdk version: 0.1.0
15:00:04.093 INFO {main} [o.e.m.opcua.sdk.server.NamespaceManager] : registered and added namespace index=2, uri=urn:org:apache:camel
15:00:04.693 INFO {ua-netty-event-loop-0} [o.e.m.o.s.server.tcp.UaTcpStackServer] : opc.tcp://127.0.0.1:12685 bound to 0.0.0.0:12685 [None/None]
15:00:04.703 INFO {ua-netty-event-loop-0} [o.e.m.o.s.server.tcp.UaTcpStackServer] : opc.tcp://172.27.56.191:12685 bound to 0.0.0.0:12685 [None/None]
15:00:04.703 INFO {ua-netty-event-loop-0} [o.e.m.o.s.server.tcp.UaTcpStackServer] : opc.tcp://192.168.56.1:12685 bound to 0.0.0.0:12685 [None/None]
15:00:04.703 INFO {ua-netty-event-loop-0} [o.e.m.o.s.server.tcp.UaTcpStackServer] : opc.tcp://srinivaska-laptop.cybage.com:12685 bound to 0.0.0.0:12685 [None/None]
15:00:04.703 INFO {ua-netty-event-loop-0} [o.e.m.o.s.server.tcp.UaTcpStackServer] : opc.tcp://srinivaska-laptop:12685 bound to 0.0.0.0:12685 [None/None]
15:00:04.723 INFO {main} [o.a.c.c.milo.client.MiloClientComponent] : Cache miss – creating new connection instance: tcp://localhost:12685
15:00:05.479 INFO {main} [o.apache.camel.spring.SpringCamelContext] : StreamCaching is not in use. If using streams then its recommended to enable stream caching. See more details at http://camel.apache.org/stream-caching.html
15:00:06.023 INFO {main} [o.apache.camel.spring.SpringCamelContext] : Route: route1 started and consuming from: timer://test
15:00:06.023 INFO {main} [o.a.c.c.m.c.internal.SubscriptionManager] : Starting connect
15:00:08.191 INFO {main} [o.apache.camel.spring.SpringCamelContext] : Route: route2 started and consuming from: milo-client://tcp://localhost:12685?node=RAW(nsu=urn:org:apache:camel;s=test-item)
Can you please add a sample code for milo-client which consume data from milo-server component.
Sure, this is already in the testing code of camel-milo: https://github.com/ctron/de.dentrassi.camel.milo/blob/master/camel-milo/src/test/java/org/apache/camel/component/milo/testing/Application.java
Hi Jens,
Is it possible to create a structure of items with multiple level (hierarchy structure) instead of a flat structure by using camel-milo server component?
Actually, I’m only able to create multiple item on the same level.
Yes, that is correct. Right now only one folder is supported. There is room for improvement :) If you would like to have this feature I would kindly ask you to create an issue at the Apache Camel JIRA. You can CC me on that.
Thanks for the answer.
Actually, the “multiple level hierarchy” is very important for us.
I cheated a little bit by using the java reflection for externally accessing the private internal property server (OpcUaServer) and creating the level by myself.