Automation Professionals' Integration Toolkit Module

Here you go:

ToolkitRPCImpl

03Feb2026 14:09:46
Unexpected error delegating to toolkitTest.gwLogInfof
java.util.NoSuchElementException: No value present

at java.base/java.util.Optional.orElseThrow(Unknown Source)

at com.automation_pros.simaids.gateway.ToolkitRPCImpl.runInGateway(ToolkitRPCImpl.java:77)

at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)

at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)

at java.base/java.lang.reflect.Method.invoke(Unknown Source)

at com.inductiveautomation.ignition.gateway.rpc.RpcDelegate$DelegateRpcHandler.handle(RpcDelegate.java:275)

at com.inductiveautomation.ignition.gateway.rpc.RpcRoutes.lambda$handle$1(RpcRoutes.java:209)

at com.inductiveautomation.ignition.gateway.rpc.RpcRoutes.safelyHandle(RpcRoutes.java:225)

at com.inductiveautomation.ignition.gateway.rpc.RpcRoutes.handle(RpcRoutes.java:209)

at com.inductiveautomation.ignition.gateway.dataroutes.Route.service(Route.java:355)

at com.inductiveautomation.ignition.gateway.dataroutes.RouteGroupImpl.service(RouteGroupImpl.java:117)

at com.inductiveautomation.ignition.gateway.dataroutes.RouteGroupCollectionServlet.serviceInternal(RouteGroupCollectionServlet.java:152)

at com.inductiveautomation.ignition.gateway.dataroutes.AbstractRouteGroupServlet.service(AbstractRouteGroupServlet.java:40)

at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:614)

at org.eclipse.jetty.ee10.servlet.ServletHolder$NotAsync.service(ServletHolder.java:1385)

at org.eclipse.jetty.ee10.servlet.ServletHolder.handle(ServletHolder.java:751)

at org.eclipse.jetty.ee10.servlet.ServletHandler$ChainEnd.doFilter(ServletHandler.java:1622)

at com.inductiveautomation.catapult.filters.GatewayFilter.doFilter(GatewayFilter.java:119)

at jakarta.servlet.http.HttpFilter.doFilter(HttpFilter.java:97)

at org.eclipse.jetty.ee10.servlet.FilterHolder.doFilter(FilterHolder.java:205)

at org.eclipse.jetty.ee10.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1594)

at org.eclipse.jetty.ee10.servlet.ServletHandler$MappedServlet.handle(ServletHandler.java:1555)

at org.eclipse.jetty.ee10.servlet.ServletChannel.dispatch(ServletChannel.java:823)

at org.eclipse.jetty.ee10.servlet.ServletChannel.handle(ServletChannel.java:440)

at org.eclipse.jetty.ee10.servlet.ServletHandler.handle(ServletHandler.java:470)

at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:575)

at org.eclipse.jetty.ee10.servlet.SessionHandler.handle(SessionHandler.java:717)

at org.eclipse.jetty.server.handler.ContextHandler.handle(ContextHandler.java:1071)

at org.eclipse.jetty.rewrite.handler.RewriteHandler$LastRuleHandler.handle(RewriteHandler.java:159)

at org.eclipse.jetty.rewrite.handler.Rule$Handler.handle(Rule.java:108)

at org.eclipse.jetty.rewrite.handler.HeaderPatternRule$1.handle(HeaderPatternRule.java:89)

at org.eclipse.jetty.rewrite.handler.Rule$Handler.handle(Rule.java:108)

at org.eclipse.jetty.rewrite.handler.HeaderPatternRule$1.handle(HeaderPatternRule.java:89)

at org.eclipse.jetty.rewrite.handler.Rule$Handler.handle(Rule.java:108)

at org.eclipse.jetty.rewrite.handler.HeaderPatternRule$1.handle(HeaderPatternRule.java:89)

at org.eclipse.jetty.rewrite.handler.Rule$Handler.handle(Rule.java:108)

at org.eclipse.jetty.rewrite.handler.HeaderPatternRule$1.handle(HeaderPatternRule.java:89)

at org.eclipse.jetty.rewrite.handler.Rule$Handler.handle(Rule.java:108)

at org.eclipse.jetty.rewrite.handler.RewriteHandler.handle(RewriteHandler.java:143)

at org.eclipse.jetty.server.Handler$Sequence.handle(Handler.java:805)

at org.eclipse.jetty.server.Handler$Sequence.handle(Handler.java:805)

at org.eclipse.jetty.server.Server.handle(Server.java:182)

at org.eclipse.jetty.server.internal.HttpChannelState$HandlerInvoker.run(HttpChannelState.java:677)

at org.eclipse.jetty.server.internal.HttpConnection.onFillable(HttpConnection.java:416)

at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:322)

at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:105)

at org.eclipse.jetty.io.SelectableChannelEndPoint$1.run(SelectableChannelEndPoint.java:53)

at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.runTask(AdaptiveExecutionStrategy.java:480)

at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.consumeTask(AdaptiveExecutionStrategy.java:443)

at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.tryProduce(AdaptiveExecutionStrategy.java:293)

at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.run(AdaptiveExecutionStrategy.java:201)

at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:311)

at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:981)

at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.doRunJob(QueuedThreadPool.java:1211)

at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:1166)

at java.base/java.lang.Thread.run(Unknown Source)

Huh. Not helpful. And seems I never properly published v2.1.2... Coming up.

For Ignition v8.3+: v2.1.2.253151852

I found this in December, and queued it up, but didn't push. ):

(v2.1.1 doesn't have the ClientReqSession material at all.)

1 Like

My example works with v2.1.2 :+1:
Thanks!

1 Like

Is there room for improvement with how lists are coerced back into PyObjects?

# Script Module (toolkitTest)
@system.util.runInGateway
def testReturnList():
	myList = []
	return myList

# Script Console
toolkitTest.testReturnList()
Java Traceback:
Traceback (most recent call last):
  File "<input>", line 3, in <module>
java.lang.ClassCastException: class java.util.Collections$UnmodifiableRandomAccessList cannot be cast to class org.python.core.PyObject (java.util.Collections$UnmodifiableRandomAccessList is in module java.base of loader 'bootstrap'; org.python.core.PyObject is in unnamed module of loader java.net.URLClassLoader @7c2bfbb3)

	at jdk.proxy2/jdk.proxy2.$Proxy86.runInGateway(Unknown Source)

	at com.automation_pros.simaids.client.script.RunInGateway$AsGatewayFunction.__gateway_call__(RunInGateway.java:51)

	at com.automation_pros.simaids.client.script.RunInGateway$AsGatewayFunction.__call__(RunInGateway.java:41)

	at com.automation_pros.simaids.client.script.RunInGateway$AsGatewayFunction.__call__(RunInGateway.java:56)

	at org.python.pycode._pyx65.f$0(<input>:3)

	at org.python.pycode._pyx65.call_function(<input>)

	at org.python.core.PyTableCode.call(PyTableCode.java:173)

	at org.python.core.PyCode.call(PyCode.java:18)

	at org.python.core.Py.runCode(Py.java:1703)

	at org.python.core.Py.exec(Py.java:1747)

	at org.python.util.PythonInterpreter.exec(PythonInterpreter.java:277)

	at org.python.util.InteractiveInterpreter.runcode(InteractiveInterpreter.java:130)

	at com.inductiveautomation.ignition.designer.gui.tools.jythonconsole.JythonConsole$ConsoleWorker.doInBackground(JythonConsole.java:639)

	at com.inductiveautomation.ignition.designer.gui.tools.jythonconsole.JythonConsole$ConsoleWorker.doInBackground(JythonConsole.java:627)

	at java.desktop/javax.swing.SwingWorker$1.call(Unknown Source)

	at java.base/java.util.concurrent.FutureTask.run(Unknown Source)

	at java.desktop/javax.swing.SwingWorker.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)

java.lang.ClassCastException: java.lang.ClassCastException: class java.util.Collections$UnmodifiableRandomAccessList cannot be cast to class org.python.core.PyObject (java.util.Collections$UnmodifiableRandomAccessList is in module java.base of loader 'bootstrap'; org.python.core.PyObject is in unnamed module of loader java.net.URLClassLoader @7c2bfbb3)


	at org.python.core.Py.JavaError(Py.java:545)

	at org.python.core.PyTableCode.call(PyTableCode.java:182)

	at org.python.core.PyCode.call(PyCode.java:18)

	at org.python.core.Py.runCode(Py.java:1703)

	at org.python.core.Py.exec(Py.java:1747)

	at org.python.util.PythonInterpreter.exec(PythonInterpreter.java:277)

	at org.python.util.InteractiveInterpreter.runcode(InteractiveInterpreter.java:130)

	at com.inductiveautomation.ignition.designer.gui.tools.jythonconsole.JythonConsole$ConsoleWorker.doInBackground(JythonConsole.java:639)

	at com.inductiveautomation.ignition.designer.gui.tools.jythonconsole.JythonConsole$ConsoleWorker.doInBackground(JythonConsole.java:627)

	at java.desktop/javax.swing.SwingWorker$1.call(Unknown Source)

	at java.base/java.util.concurrent.FutureTask.run(Unknown Source)

	at java.desktop/javax.swing.SwingWorker.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 java.util.Collections$UnmodifiableRandomAccessList cannot be cast to class org.python.core.PyObject (java.util.Collections$UnmodifiableRandomAccessList is in module java.base of loader 'bootstrap'; org.python.core.PyObject is in unnamed module of loader java.net.URLClassLoader @7c2bfbb3)

	at jdk.proxy2/jdk.proxy2.$Proxy86.runInGateway(Unknown Source)

	at com.automation_pros.simaids.client.script.RunInGateway$AsGatewayFunction.__gateway_call__(RunInGateway.java:51)

	at com.automation_pros.simaids.client.script.RunInGateway$AsGatewayFunction.__call__(RunInGateway.java:41)

	at com.automation_pros.simaids.client.script.RunInGateway$AsGatewayFunction.__call__(RunInGateway.java:56)

	at org.python.pycode._pyx65.f$0(<input>:3)

	at org.python.pycode._pyx65.call_function(<input>)

	at org.python.core.PyTableCode.call(PyTableCode.java:173)

	... 13 more

Traceback (most recent call last):
  File "<input>", line 3, in <module>
java.lang.ClassCastException: class java.util.Collections$UnmodifiableRandomAccessList cannot be cast to class org.python.core.PyObject (java.util.Collections$UnmodifiableRandomAccessList is in module java.base of loader 'bootstrap'; org.python.core.PyObject is in unnamed module of loader java.net.URLClassLoader @7c2bfbb3)

	at jdk.proxy2/jdk.proxy2.$Proxy86.runInGateway(Unknown Source)

	at com.automation_pros.simaids.client.script.RunInGateway$AsGatewayFunction.__gateway_call__(RunInGateway.java:51)

	at com.automation_pros.simaids.client.script.RunInGateway$AsGatewayFunction.__call__(RunInGateway.java:41)

	at com.automation_pros.simaids.client.script.RunInGateway$AsGatewayFunction.__call__(RunInGateway.java:56)

	at org.python.pycode._pyx65.f$0(<input>:3)

	at org.python.pycode._pyx65.call_function(<input>)

	at org.python.core.PyTableCode.call(PyTableCode.java:173)

	at org.python.core.PyCode.call(PyCode.java:18)

	at org.python.core.Py.runCode(Py.java:1703)

	at org.python.core.Py.exec(Py.java:1747)

	at org.python.util.PythonInterpreter.exec(PythonInterpreter.java:277)

	at org.python.util.InteractiveInterpreter.runcode(InteractiveInterpreter.java:130)

	at com.inductiveautomation.ignition.designer.gui.tools.jythonconsole.JythonConsole$ConsoleWorker.doInBackground(JythonConsole.java:639)

	at com.inductiveautomation.ignition.designer.gui.tools.jythonconsole.JythonConsole$ConsoleWorker.doInBackground(JythonConsole.java:627)

	at java.desktop/javax.swing.SwingWorker$1.call(Unknown Source)

	at java.base/java.util.concurrent.FutureTask.run(Unknown Source)

	at java.desktop/javax.swing.SwingWorker.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)

java.lang.ClassCastException: java.lang.ClassCastException: class java.util.Collections$UnmodifiableRandomAccessList cannot be cast to class org.python.core.PyObject (java.util.Collections$UnmodifiableRandomAccessList is in module java.base of loader 'bootstrap'; org.python.core.PyObject is in unnamed module of loader java.net.URLClassLoader @7c2bfbb3)

The inevitable pain of (de)serialization is part of the reason I have been so hesitant to do something like this. Looks like Phil's using the base proto based RPC serialization in 8.3, which hands back real (unmodifiable) List instances when given one over RPC, instead of any wrapped Jython thing.

Will investigate.

1 Like