I am trying to interface with a vendor's api with uses 'socket.io' as an interface process. I had to refractor both libraries and place them into a an uber-jar to avoid the io.py module naming-conflict. Now, when I run a main class on Netbeans, I am able to reach the socket serverio -- great! But when I import the jar into the Gateway and Designer folders, I am able create a socketio object, it just not seem to do anything... it would make method calls and it will not connect. The portion I wrote in Script Console is as close to the Main Class as I wrote in Java and that works.... I am stuck.
from logicz.io.socket.client import IO
from logicz.io.socket.client import Socket
from logicz.io.socket.emitter import Emitter
from java.lang.reflect import Array
from java.net import URI
from java.util import Arrays
from java.util import ArrayList
from java.util import HashMap
from java.util import List
from java.util import Map
#----------------------------------------#
# In Java, Emitter.Listener is an Interface Class with one
# method-- call(Object...args){}
# Inherit class and, presumably, override method
class Listener_Any(Emitter.Listener):
def call(self,*args, **kwargs):
print args
class Listener_CONNECT(Emitter.Listener):
def call(self,*args):
print("CONNECTED!")
#---------------------------------------#
if __name__ == "__main__":
url = "https://somecompany.com"
# In Java, I used a hashmap successfully
headers = HashMap()
headers.put("Authorization",
"someHasheads234o534nejrgtn")
headers.put("InstallationId",
"adsfasd-sfgthtrherwt-asdfda")
# In java: String[] transport = {"websocket"};
transport = ArrayList()
transport.append("websocket")
passedInGroupIds = "groupIds=1"
# This builds the options for the socket.io connection
options = IO.Options().builder()\
.setForceNew(False)\
.setMultiplex(True)\
.setTransports(transport)\
.setUpgrade(True)\
.setRememberUpgrade(False)\
.setPath("/api/oid/v1/")\
.setQuery(passedInGroupIds)\
.setExtraHeaders( headers )\
.setReconnection(True)\
.setReconnectionAttempts(3)\
.setReconnectionDelay(1000)\
.setReconnectionDelayMax(5000)\
.setRandomizationFactor(0.5)\
.setTimeout(5000)\
.build()
# Create the connection onject
socket = IO.socket(URI.create(url), options)
# Define what events to listen to.. here is on-connecction
socket.on(Socket.EVENT_CONNECT, Listener_CONNECT())
# Define what events to listen to.. here is listen to all events
socket=socket.onAnyIncoming( Listener_Any() )
# This should activate the socket connection
socket.connect()
So, the Emitter.Listener is a Java Interface Class, which needs an method override
public static interface Listener {
public void call(Object... args);
}
In the git-hub library's readme / test-example, the 'socket' object stores these "socket.on.(, <Emitter.Listener>() )" method calls in a collection of Listeners which are someone waiting for those specified events to be generated from the server. Different method overrides seem to be perfectly fine in Netbeans -- here's one variant I have been using with Success
Oooh, my mistake. Sorry. It was early and I was on mobile. I see now those are classes implementing an interface and not callback functions.
I wonder if it's working but those callbacks are being made on a different thread and that causes the print statements to not get picked up by the console or something. Try writing to a memory tag in addition to printing?
I'm not convinced either of these overloads you're attempting to use are actually being called by Jython. Emitter.Listener seems to expect a Java object array; the naive way I would expect that to translate to Jython would be a *args, but Jython might not actually be calling your implementation at all. Try a few different syntaxes for def call, e.g. def call(self), def call(self, args) and see if any of them get called.
I would also use system.util.getLogger to confirm any output from your scripts.
I created my Jython interface class to create the Java objects...
# Define a class that interfaces with the Java Socket.IO library
class SocketIOClient:
def __init__(self, uri, **options):
self.logger = system.util.getLogger("SocketIO")
# Create an IO.Options object
io_options = IO.Options()
# Convert and set path if provided
if 'path' in options:
io_options.path = options['path']
# Convert and set transports if provided
if 'transports' in options:
java_transports = ArrayList()
for transport in options['transports']:
java_transports.add(transport)
io_options.transports = java_transports.toArray([String]*java_transports.size())
# blah, blah, blah
and I even wrote my listener classes which should were, in theory, overriding the Java interface class Listener. However, these the Listener method's were never being called by the socketio object... That is, until I embedded the new Listener Class INSIDE my SocketIO class... then everything worked.
# Define a class that interfaces with the Java Socket.IO library
class SocketIOClient:
# Define the AnyListener inner class
class AnyListener(Emitter.Listener):
def call(self, args):
# Here you can handle any incoming packets
# args is an array of objects received in the packet
payload = {}
payload["subscription"] = str(args[0])
I honestly don't know why it worked.. it was a hail-mary. Also, playing around with the args, *args, and **kwargs was helpful! Well @PGriffith , @Kevin.Herron , thank you again for the pointers!