Add .JAR for using classes in Jython scripts

Hi @Pramanj, I’m curious how you achieved this.
I’m also testing on a 7.9.10 install and was unable to import the Logger.class as a test.
I tried dropping pubnub-3.4.jar into the lib/core/common directory. When I ran from com.pubnub.api import Logger in the script console I got ImportError: No module named pubnub

I’m trying to learn more about these areas of Ignition so any insight would be greatly appreciated.
My end goal would be to achieve exactly what the OP wanted to do with regards to poi-ooxml-4.1.0.jar.
My idea is to get this jar working as you described, then trying to build a module for it.

I was able to get this to work.

I used pack200 to create a pack.gz and placed the jar and the pack.gz files in the lib/core/common.
I restarted the gateway and my designer and I was able to run from com.pubnub.api import Logger without any errors.

Thanks to @Kevin.Herron in this post: Adding java custom classes to Ignition

NOTE* his disclaimer about official support and the SDK is the way to go.

I placed my jars in gateway scope and I was able to access thru gateway scripts in 7.9.10. However for version 8, I too had to restart the gateway and designer once for it to work.
Are you using these jars from modules or from scripts?

Of course sdk is the recommended way but a dreaded the whole process of building empty modules and keeping versions of it for each version of Ignition. So I took the shortcut and it worked (atleast for 7.9.10)

Then don’t build empty modules. Put the jars you are deploying into the modules like they’re supposed to be, with a script class that exposes the import objects from the jars in the Ignition system.* namespace. You should do the work to make it easy on your potential customers. Don’t make them responsible for placing jars in the right places. They might not have convenient filesystem access, but be able to use the module install page in the gateway.

2 Likes

But I don’t have any modules ! I simply have jython scripts in gateway that use the libraries from this jar! If at all I have to build a module in gateway scope, then I have to use the skeleton gateway module that’s auto generated by maven archetypes for Ignition, and import some functions from these jars without using any of them it it and build the module! That’s what I meant by empty module. I hope my point is clear, or I am missing something?

Not clear! I am including an import statement in the skeleton module which uses some of the functions from this jar. Hope that’s what you mean? I am actually not using any function in the code of the module.

I guess I will have to eventually make such an empty module and try to Install in Ignition as a regular module which will install the jars in appropriate directories. The biggest advantage besides users convenience is that they can be installed in gateway without having to restart it!

Scripts. I’m working my way to building a module for it so users can use the system.* namespace in there scripts.

My end goal is to expose the apache poi 4.1.0 to end users. I’ve been digging around the forums and I’m wondering if my end goal is not possible? Kevin mentions a weird corner case about possible conflicts with the reporting module because it uses poi-3.14.

I’m looking for a kick start in the right direction (Uninstalling the reporting module isn’t an option for our client); is 4.1.0 not a good idea because of the reporting module? Is it a safer bet to use the same version as the reporting module? Is it possible to just access the existing POI library from all scopes?

Yes, you’ll have to use the same version as Reporting.

Only if your module adds it to all scopes. It’s added to C/D by Reporting, not gateway.

1 Like

How come import org.apache.poi fails to import in the designer if the reporting modules adds it to the D scope?

I would think it’s possible since there already exists a third-party wrapper module for Apache POI, by Perfect Abstractions: http://blog.perfectabstractions.com/2017/04/05/using-the-pa-office-document-module/

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