I have one module, in which I have created the method.
Now I wanted to call the methods of my module into another module.
Lets pretend this is the module you wrote -
myModule
def foo():
pass
Then in your other module
import myModule
myModule.foo()
Assuming you are using the scripting modules section.
This is the "Module Development" category for SDK modules.
For complete access to one module's classes and methods from another, you would make the first module a declared dependency of the second module (in module.xml). This will make the second module's classloader a child of the first module's classloader.
If you cannot do this (some other dependency interferes, perhaps), then you will have to use an indirect access method. If you look at the javadocs for CommonContext, you will see a getModule() method that returns a different module's gateway hook. You can use this from your second module to obtain a reference to your first module's gateway hook. That hook must expose methods you can use to obtain any other class instances you need.
Whoops, I didnât see the category tag. Ignore what I said.
@pturmel thank you for this suggestion: That hook must expose methods you can use to obtain any other class instances you need.
I have tried to implement it:
- by creating a new interface (called IGatewayHook, that extends the standard GatewayModuleHook), where the method getProviders is declared, in order to obtain the âproviderâ instances from the other module.
- by adding the implementation of IGatewayHook to the GatewayHook classes of the two modules (in order to implement the getProviders method).
- by calling from one module the following:
baseModuleHook = (IGatewayHook) context.getModuleManager().getModule("com.xxx.ignition.kernel.base").getHook();
The last instruction throws the ClassCastException exception:
java.lang.Exception: Exception while starting up module "com.xxx.ignition.kernel.simulation".
at com.inductiveautomation.ignition.gateway.modules.ModuleManagerImpl$LoadedModule.startup(ModuleManagerImpl.java:2439)
at com.inductiveautomation.ignition.gateway.modules.ModuleManagerImpl.startupModule(ModuleManagerImpl.java:1226)
at com.inductiveautomation.ignition.gateway.modules.ModuleManagerImpl$2.call(ModuleManagerImpl.java:771)
at com.inductiveautomation.ignition.gateway.modules.ModuleManagerImpl.executeModuleOperation(ModuleManagerImpl.java:947)
at com.inductiveautomation.ignition.gateway.modules.ModuleManagerImpl.installModuleInternal(ModuleManagerImpl.java:737)
at com.inductiveautomation.ignition.gateway.modules.ModuleManagerImpl$InstallCommand.execute(ModuleManagerImpl.java:1903)
at com.inductiveautomation.ignition.gateway.modules.ModuleManagerImpl$Receiver.receiveCall(ModuleManagerImpl.java:1856)
at com.inductiveautomation.ignition.gateway.redundancy.QueueableMessageReceiver.receiveCall(QueueableMessageReceiver.java:47)
at com.inductiveautomation.ignition.gateway.redundancy.RedundancyManagerImpl.dispatchMessage(RedundancyManagerImpl.java:933)
at com.inductiveautomation.ignition.gateway.redundancy.RedundancyManagerImpl$ExecuteTask.run(RedundancyManagerImpl.java:1008)
at com.inductiveautomation.ignition.common.execution.impl.BasicExecutionEngine$ThrowableCatchingRunnable.run(BasicExecutionEngine.java:518)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
at java.base/java.util.concurrent.FutureTask.run(Unknown Source)
at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.base/java.lang.Thread.run(Unknown Source)
Caused by: java.lang.ClassCastException: class com.xxx.ignition.kernel.provider.GatewayHook cannot be cast to class com.xxx.ignition.kernel.provider.IGatewayHook (com.xxx.ignition.kernel.provider.GatewayHook is in unnamed module of loader com.inductiveautomation.ignition.gateway.modules.ModuleClassLoader @10a94db3; com.xxx.ignition.kernel.provider.IGatewayHook is in unnamed module of loader com.inductiveautomation.ignition.gateway.modules.ModuleClassLoader @27a7482e)
at com.xxx.ignition.kernel.provider.simulation.GatewayHook.startup(GatewayHook.java:45)
at com.inductiveautomation.ignition.gateway.modules.ModuleManagerImpl$LoadedModule.startup(ModuleManagerImpl.java:2433)
... 16 more
8.0.17 (b2020111211)
Azul Systems, Inc. 11.0.7
where the cast is not allowed: I do not understand why. Could you help me?
Thank you very much in advance.
Best,
Andrea
Modules are loaded in their own isolated ClassLoader. If you want to be able to reference something from module âAâ in your module âBâ then you have to mark module âBâ as depending on module âAâ, which will cause âAââs ClassLoader to be the parent ClassLoader for âBâ.
An interface wonât help. You canât retroactively apply such to the other moduleâs hook. I should have pointed out that you will probably have to use reflection to access anything that isnât already declared in GatewayModuleHook
.
Thank you @Kevin.Herron.
The dependency has been added, in effect the instances of the other module are accessible via debug mode.
Thank you @pturmel, I am going to work on what you suggested!
Hi @Kevin.Herron,
a better clarification: to create the module dependency, it is enough to have on module B pom file the below part?
<dependencies>
<dependency>
<groupId>com.xxx.ignition</groupId>
<artifactId>moduleA</artifactId>
<version>x.y</version>
</dependency>
</dependencies>
I follow the userguide in Understanding Class Loaders - Ignition SDK Programmerâs Guide - Ignition Documentation (inductiveautomation.com), but there isnât any reference to the pom structure and I am not sure to be on the right way!
I wouldnât expect that to be enough. You have to end up with a <depends>
entry in your module.xml
file. (I still donât use maven and its Ignition plug, so I canât be more specific.)
Hereâs what weâve used, and is working with Maven. The key as was pointed out is the depends section.
<build>
<plugins>
<plugin>
<groupId>com.inductiveautomation.ignitionsdk</groupId>
<artifactId>ignition-maven-plugin</artifactId>
<version>1.1.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>modl</goal>
</goals>
</execution>
</executions>
<configuration>
<projectScopes>
<projectScope>
<name>package-client</name>
<scope>C</scope>
</projectScope>
<projectScope>
<name>package-common</name>
<scope>CDG</scope>
</projectScope>
<projectScope>
<name>package-designer</name>
<scope>CD</scope>
</projectScope>
<projectScope>
<name>package-gateway</name>
<scope>G</scope>
</projectScope>
</projectScopes>
<moduleId>com.package</moduleId>
<moduleName>${project.parent.name}</moduleName>
<moduleDescription>${project.description}</moduleDescription>
<moduleVersion>${project.version}</moduleVersion>
<requiredIgnitionVersion>8.1.0</requiredIgnitionVersion>
<requiredFrameworkVersion>8</requiredFrameworkVersion>
<licenseFile>License.html</licenseFile>
<depends>
<depend>
<scope>CDG</scope>
<moduleId>com.otherpackage</moduleId>
</depend>
</depends>
<hooks>
<hook>
<scope>C</scope>
<hookClass>com.package.client.ClientHook</hookClass>
</hook>
<hook>
<scope>D</scope>
<hookClass>com.package.designer.DesignerHook</hookClass>
</hook>
<hook>
<scope>G</scope>
<hookClass>com.package.gateway.GatewayHook</hookClass>
</hook>
</hooks>
</configuration>
</plugin>
</plugins>
</build>
How does one get the context object to start?
(Iâm new to java, maven, and intellij)
This page: Read and Write Tags - Ignition SDK Programmer's Guide - Ignition Documentation
says:
IgnitionGateway context = IgnitionGateway.get();
but the fine print at the top says âassumes that the GatewayContext object is availableâ
I started with the example scripting-function module from: GitHub - inductiveautomation/ignition-sdk-examples: Ignition SDK Example Projects and added that context line inside the GatewayScriptModuleâs multiplyImpl function body and get the error:
Cannot resolve symbol âIgnitionGatewayâ
Using Ignition 8.0.13
Hmm, those are poor examples. The IgnitionGateway
class is not part of the public API/SDK. I think youâre supposed to ignore that part and thatâs why it says the assumption is you have a GatewayContext
.
Your module gets the GatewayContext
in the GatewayModuleHook::setup
call. You can pass it around as needed.