BundleUtil confusion - ModbusDriverExample shows incorrect name/description

I am looking into implementing a driver but I am completely confused by the localisation system, BundleUtil, etc. I tried building and installing the ModbusDriverExample and it seems that it doesn’t work there either.

Instead of using the Modbus.properties file, the “Create new device” page shows the following text:


Note: I am using the ignition-7.9 branch of the ignition-sdk-examples repository.

The documentation for DriverType states that this takes a nameKey and descriptionKey which will be passed to BundleUtil. Is this correct? Perhaps these should just be plain strings?

Or is there something wrong with the example? An issue with the build scripts? An issue with my build environment?

Also, please could somebody review the documentation for BundleUtil. It’s not clear at all how this works.

  • What class am I supposed to pass to addBundle? How do I add a single properties file that’s available to all the classes in my module?
  • Why does the shortcut say it’s equivalent to passing clazz.getClassLoader() instead of just clazz?
  • Why do the example modules have the .properties files in a separate src/main/resources tree? Do we have to do this? Aside from being horrible it also contradicts the documentation which states that the .properties files should be alongside the .java files.


In this case, it seems like the problem is that Modbus.properties isn’t in src/main/resources/parallel/path/to/ModbusDriver.java.

If you move it and then mvn clean package it should build a driver that loads the properties file correctly.

As far why it’s that way … it just is. That’s Maven convention.

mkdir -p ModbusDriverExample/mde-gateway/src/main/resources/com/inductiveautomation/xopc/drivers/modbus2/
mv ModbusDriverExample/mde-gateway/src/main/java/com/inductiveautomation/xopc/drivers/modbus2/Modbus.properties ModbusDriverExample/mde-gateway/src/main/resources/com/inductiveautomation/xopc/drivers/modbus2/
mvn clean package

Uninstalled module (is this necessary?), uploaded new module. No change.

Any changes to properties files usually require a gateway restart to take effect.

It seems the properties files for the PersistentRecords are also in the wrong location. I don’t know if there was previously some configuration that made this work or if something went wrong when this got dumped and modified to be an SDK example.

Restarting the gateway has fixed it. That makes this impossible to debug.

We don’t have a chance of getting this working on our own without better examples and better documentation. The whole thing is confusing enough as it is without the examples being wrong and nothing happening unless the gateway is restarted :frowning:

I would strongly suggest that the documentation should make it very clear that changes to properties files require a gateway restart. Although even better would be to make this work as expected!

I’ll relocate the properties files and update the 7.9 examples.

FWIW, I think these extension point types are one of the only places you’re forced to use BundleUtil and deal with the localization/properties files. Even PersistentRecords are a little easier because they don’t require the properties file to be loaded with BundleUtil.

Docs could always be better, of course…

My module is now working as well. It turns out I had fixed it, but I had no idea because I hadn’t restarted the gateway yet!

If there is some way to make these work in the same tree I would love to know about it. The separate parallel trees seem incredibly bug prone to me.

It’s a quirk of BundleUtil. Most other changes you would make will not require a gateway restart.

I don’t know what you’re working on here, but I should at least warn you that this example is very dated and is not representative of how newer drivers are architected.

Unfortunately I don’t have any good examples of this, in either 7.9 or 8.0, but I’m hoping in the near* future to open source another driver example. Probably something simple like a Micro800 driver. But it will only be built for 8.0 and be an example for the new driver API in 8.0.

*this year? maybe?


I noticed the API for 8.0 looked quite different. Unfortunately I’m having to stick with 7.9 for this one. Or are you saying there is a better way of doing this in 7.9 as well?

10,000 foot view of what you should do different:

  1. Protocol implementation should not be coupled to the driver implementation. For example, when I eventually rewrite the Modbus driver, I’ll just use this implementation I built. The driver should just focus on the integration of some protocol into the OPC UA server.

  2. Don’t extend from AbstractDriver, just implement the Driver interface directly. AbstractDriver is basically a state machine always trying to force a driver into the Connected state, among other weird things. It’s a design that we came up with over 10 years (!!!) ago, and has proved to be troublesome.

+1000000000. When I started my Ethernet/IP driver, I beat my head on the AbstractDriver for a while. :hot_face:

@systemparadox make David send you to ICC this year so you can get all the advice you want in person.

I think you mean Alasdair, but yes, I really should go to ICC sometime!

Ah that’s good. I already decided that AbstractDriver didn’t fit well with what we’re doing so it’s nice to know I’m actually on track instead of in the wilds.

May I suggest at least updating the SDK guide to point new developers away from AbstractDriver instead of towards it?


Oops :flushed:

Yes, I meant Alasdair.

I could be convinced to cross the pond for some Module building consulting… Maybe even a discounted rate… (: