Add .JAR for using classes in Jython scripts

His office module uses poi version 3.14.

2 Likes

I don't know. What exactly are you trying to import and where?

From the designer’s Script Console:
from org.apache.poi.xssf.usermodel import XSSFWorkbook
returns
ImportError: No module named poi

Do you have the Reporting module installed?

Also: XSSFWorkbook is not part of poi-3.14 jar

Yes, the reporting module is installed.

If this is not apart of 3.14 then the Perfect Abstraction module must be using a different version.
The link above from @bfuson has sample code that uses XSSFWorkbook.

It’s not using a different version, you can unzip it and look yourself. It does include additional poi jars, though…

Thanks for your patience Kevin. I’m following now.

Is this still correct today? You cannot make a java library available in the gateway scope from a .jar within a module without making system.* methods for every method in the library?

You might be able to lift the contents of a JAR provided by your module into a higher ClassLoader using the export element in module.xml:

<export scope="G">some-library.jar</export>

Careful, it’s probably super dangerous and might cause a memory leak if you restart the module.

I want to use the library on a production system. This sounds too risky. Dropping the jar into lib/core/common after every upgrade sounds less risky, but still a pain because you have to remember to do that.

Is there a reason why there is not native support for adding a jar to the gateway scope?

It's dangerous. Modules have isolated ClassLoaders by default. If they all shared a ClassLoader, or when you start exporting stuff to a higher ClassLoader, you now have to worry about making sure that you don't export a library or class that the gateway or any other module uses, or that you don't export an incompatible version, etc. And it's easy to cause a memory leak when a module can reach up and register something like this in the gateway, which can then in turn be referenced and hung onto by scripting. :scream:

edit: and it's just not supported outside of modules because it makes upgrade logic go from dead simple to complicated enough it'll probably be wrong in some cases. Right now it's easy: wipe out the library directories and then replace them. No state to keep track of. No figuring out what versions of what libraries are in what version of Ignition, or diffing to figure out if a user added one.

People already regularly screw up zip distribution upgrades by thinking they can just unzip on top of the existing install, but when a library goes from foo-1.0.0.jar to foo-1.1.0.jar you suddenly have 2 different versions of the same library on the ClassPath and get non-deterministic behavior.

1 Like

Thanks for the thorough response. If we go with dropping the jar in lib/core/common, other than the pain of us having to keep track of adding it back in after upgrades, what risk are we taking on? Is this something that could stop working in future releases of Ignition?

I think that’s pretty unlikely to stop working. The biggest risk is procedural, which you already understand. The library doesn’t come along with backups or upgrades.

You previously mentioned gateway scope, but are now talking about lib/core/common. If you only need it in gateway scope you can use lib/core/gateway. By putting it in common it’s also forcing the library to be downloaded by the Designer and Clients.

1 Like

You might find this topic helpful, particularly the public release of my FieldClassBuilder:

Note that this permits controlled exposure of classes in your module's classloader (normal jar) to any desired system.* namespaces without having to manually construct them when you change jar versions. I use this to accept many different versions of an externally-installed OpenCV jar (due to licensing, it cannot be packaged in a module) but still expose (nearly) all of its member classes.

1 Like

Manually dropping jars in lib/core/gateway works fine but needs restarting of the gateway to be visible to scripts. On upgrading Ignition version these jars will still be visible. However, if you need to upgrade the jars then you have to delete the current one and add new ones and obviously restart the gateway.

This is the way.