crossbar.io: reasons why onJoin() might not be called?

#1

Hi all,

I’m trying to take an existing class which extends ApplicationSession and get crossbar.io to start it for me, along with starting a router for it. I started by typing:

crossbar init --template hello:python --appdir hello

and then trying to modify what was generated to match my situation. My modified config.json looks like this:

{

“controller”: {

},

“workers”: [

  {

     "type": "router",

     "options": {

        "pythonpath": [".."]

     },

     "realms": [

        {

           "name": "vtkweb",

           "roles": [

              {

                 "name": "anonymous",

                 "permissions": [

                    {

                       "uri": "*",

                       "publish": true,

                       "subscribe": true,

                       "call": true,

                       "register": true

                    }

                 ]

              }

           ]

        }

     ],

     "transports": [

        {

           "type": "web",

           "endpoint": {

              "type": "tcp",

              "port": 8080

           },

           "paths": {

              "/": {

                 "type": "static",

                 "directory": ".../www"

              },

              "ws": {

                 "type": "websocket"

              }

           }

        }

     ]

  },

  {

     "type": "container",

     "options": {

        "pythonpath": [".../lib/site-packages",".../lib"]

     },

     "components": [

        {

           "type": "class",

           "classname": "paraview.web.pv_web_visualizer._VisualizerServer",

           "realm": "vtkweb",

           "transport": {

              "type": "websocket",

              "endpoint": {

                 "type": "tcp",

                 "host": "127.0.0.1",

                 "port": 8080

              },

              "url": "ws://[127.0.0.1:8080/ws](http://127.0.0.1:8080/ws)"

           }

        }

     ]

  }

]

}

And here is my modified setup.py (Is this actually needed, or might the config.json be enough?):

from setuptools import setup

setup(

name = 'pvtest',

version = '0.0.1',

description = "'pvtest' WAMP Component",

platforms = ['Any'],

packages = ['paraview'],

include_package_data = True,

zip_safe = False,

entry_points = {

    'autobahn.twisted.wamplet': [

        'backend = paraview.web.pv_web_visualizer:_VisualizerServer'

    ],

}

)

Here is what I am pretty sure is working:

  1. the static site is up and working, I can load content from the directory I have specified

  2. I have run crossbar with “-d” and used logging to verify that my ApplicationSession component is getting constructed. But the onJoin() method is never called. If I understand correctly (a huge assumption here), onJoin() should be called when the transport is set up, which is something that happens between the router and the application component. Is that correct?

So, does anyone see something obvious I could be doing wrong? Any idea why my onJoin() method is never called?

Thanks!

Scott

0 Likes

#2

Hi Scott,

> I'm trying to take an existing class which extends

ApplicationSession and get crossbar.io <http://crossbar.io> to start it
for me, along with starting a router for it. I started by typing:

crossbar init --template hello:python --appdir hello

That's a good way to start, since you can first assure yourself that the (unmodifed) thing actually works (know-good) and then tweak from there.

and then trying to modify what was generated to match my situation. My
modified config.json looks like this:

{
    "controller": {
    },
    "workers": [
       {
          "type": "router",
          "options": {
             "pythonpath": [".."]
          },
          "realms": [
             {
                "name": "vtkweb",
                "roles": [
                   {
                      "name": "anonymous",
                      "permissions": [
                         {
                            "uri": "*",
                            "publish": true,
                            "subscribe": true,
                            "call": true,
                            "register": true
                         }
                      ]
                   }
                ]
             }
          ],
          "transports": [
             {
                "type": "web",
                "endpoint": {
                   "type": "tcp",
                   "port": 8080
                },
                "paths": {
                   "/": {
                      "type": "static",
                      "directory": ".../www"
                   },
                   "ws": {
                      "type": "websocket"
                   }
                }
             }
          ]
       },
       {
          "type": "container",
          "options": {
             "pythonpath": [".../lib/site-packages",".../lib"]
          },
          "components": [
             {
                "type": "class",
                "classname":
"paraview.web.pv_web_visualizer._VisualizerServer",
                "realm": "vtkweb",
                "transport": {
                   "type": "websocket",
                   "endpoint": {
                      "type": "tcp",
                      "host": "127.0.0.1",
                      "port": 8080
                   },
                   "url": "ws://127.0.0.1:8080/ws
<http://127.0.0.1:8080/ws>"
                }
             }
          ]
       }
    ]
}

This looks good to me (not sure about the 3 dots .. why 3 and not 2?)

Is your dir structure like this?

hello/.crossbar
hello/lib
hello/lib/site-packages
hello/lib/site-packages/paraview/web/pv_web_visualizer.py

and a class

class _VisualizerServer(ApplicationSession)

in pv_web_visualizer.py?

Since this is where CB would look after the component.

Probably you could send the output of

ls -la hello

to let me check (discloses the filenames of your app .. if that is ok for you).

Or check manually that the file is syntactically correct and can be found

cd .crossbar
PYTHONPATH=".../lib/site-packages;.../lib" python -m paraview.web.pv_web_visualizer

And here is my modified setup.py (Is this actually needed, or might the
config.json be enough?):

If you are using a component of type "class", you don't need the setup.py at all.

With "class", all that is needed is the "classname" and "pythonpath" in config.

The "setup.py" is when you want to distribute your component as a proper Python package. If you do so, then you would use type "wamplet" as component type. CB then finds your class via the "entry_points" from the setup.py

..

Here is what I am pretty sure is working:

1) the static site is up and working, I can load content from the
directory I have specified

2) I have run crossbar with "-d" and used logging to verify that my
ApplicationSession component is getting constructed. But the onJoin()
method is never called. If I understand correctly (a huge assumption
here), onJoin() should be called when the transport is set up, which is
something that happens between the router and the application component.
  Is that correct?

Nearly.

A component connects to a router over a WAMP transport. When the transport is established, the onConnect() callback on your ApplicationSession fires. The default implementation of onConnect() then calls join() to actually attach the session to a realm.

When the session then actually has attached, the onJoin() callback fires. Now the session is ready.

Note: between onConnect() and onJoin() there are authentication related callbacks.

So, does anyone see something obvious I could be doing wrong? Any idea
why my onJoin() method is never called?

Could you modify your config for

                   "url": "ws://127.0.0.1:8080/ws",
                   "debug": true

and send us log output?

···

Thanks!
Scott

--
You received this message because you are subscribed to the Google
Groups "Autobahn" group.
To unsubscribe from this group and stop receiving emails from it, send
an email to autobahnws+...@googlegroups.com
<mailto:autobahnws+...@googlegroups.com>.
To post to this group, send email to autob...@googlegroups.com
<mailto:autob...@googlegroups.com>.
To view this discussion on the web visit
https://groups.google.com/d/msgid/autobahnws/CAPiw4fCNgnQh0TSUT1P_sgWYHaj0oo%3D8_gGZrSQvki5dDadAnw%40mail.gmail.com
<https://groups.google.com/d/msgid/autobahnws/CAPiw4fCNgnQh0TSUT1P_sgWYHaj0oo%3D8_gGZrSQvki5dDadAnw%40mail.gmail.com?utm_medium=email&utm_source=footer>.
For more options, visit https://groups.google.com/d/optout.

0 Likes

#3

Hi Tobias,

Sorry to take so long to respond, I usually see an email in my inbox, but this time I didn’t. I’m glad I finally came back to the forum to check! Anyway, thanks for responding so quickly :slight_smile:

My replies are inlined, I really appreciate your help, thanks!

Hi Scott,

I'm trying to take an existing class which extends

ApplicationSession and get crossbar.io <http://crossbar.io> to start it

for me, along with starting a router for it. I started by typing:

crossbar init --template hello:python --appdir hello

That’s a good way to start, since you can first assure yourself that the
(unmodifed) thing actually works (know-good) and then tweak from there.

Yep, the basic one worked just great. Specifically, no problem with rpc call registered on the server and called from the Javascript client.

and then trying to modify what was generated to match my situation. My

modified config.json looks like this:

{

"controller": {
},
"workers": [
   {
      "type": "router",
      "options": {
         "pythonpath": [".."]
      },
      "realms": [
         {
            "name": "vtkweb",
            "roles": [
               {
                  "name": "anonymous",
                  "permissions": [
                     {
                        "uri": "*",
                        "publish": true,
                        "subscribe": true,
                        "call": true,
                        "register": true
                     }
                  ]
               }
            ]
         }
      ],
      "transports": [
         {
            "type": "web",
            "endpoint": {
               "type": "tcp",
               "port": 8080
            },
            "paths": {
               "/": {
                  "type": "static",
                  "directory": ".../www"
               },
               "ws": {
                  "type": "websocket"
               }
            }
         }
      ]
   },
   {
      "type": "container",
      "options": {
         "pythonpath": [".../lib/site-packages",".../lib"]
      },
      "components": [
         {
            "type": "class",
            "classname":

“paraview.web.pv_web_visualizer._VisualizerServer”,

            "realm": "vtkweb",
            "transport": {
               "type": "websocket",
               "endpoint": {
                  "type": "tcp",
                  "host": "127.0.0.1",
                  "port": 8080
               },
               "url": "ws://[127.0.0.1:8080/ws](http://127.0.0.1:8080/ws)

<http://127.0.0.1:8080/ws>"

            }
         }
      ]
   }
]

}

This looks good to me (not sure about the 3 dots … why 3 and not 2?)

Is your dir structure like this?

hello/.crossbar

hello/lib

hello/lib/site-packages

hello/lib/site-packages/paraview/web/pv_web_visualizer.py

and a class

class _VisualizerServer(ApplicationSession)

in pv_web_visualizer.py?

Since this is where CB would look after the component.

Probably you could send the output of

ls -la hello

to let me check (discloses the filenames of your app … if that is ok
for you).

Or check manually that the file is syntactically correct and can be found

cd .crossbar

PYTHONPATH="…/lib/site-packages;…/lib" python -m
paraview.web.pv_web_visualizer

Sorry for introducing that confusion, the three dots were meant to indicate “stuff left out”. The path is actually an absolute one, and I think it’s fine because I figured out how to log from my application component, and I can see I’m getting inside a couple methods of my class. As you’ll see in my log output.

And here is my modified setup.py (Is this actually needed, or might the

config.json be enough?):

If you are using a component of type “class”, you don’t need the
setup.py at all.

With “class”, all that is needed is the “classname” and “pythonpath” in
config.

The “setup.py” is when you want to distribute your component as a proper
Python package. If you do so, then you would use type “wamplet” as
component type. CB then finds your class via the “entry_points” from the
setup.py

This is great, just what we were hoping for !

Here is what I am pretty sure is working:

  1. the static site is up and working, I can load content from the

directory I have specified

  1. I have run crossbar with “-d” and used logging to verify that my

ApplicationSession component is getting constructed. But the onJoin()

method is never called. If I understand correctly (a huge assumption

here), onJoin() should be called when the transport is set up, which is

something that happens between the router and the application component.

Is that correct?

Nearly.

A component connects to a router over a WAMP transport. When the
transport is established, the onConnect() callback on your
ApplicationSession fires. The default implementation of onConnect() then
calls join() to actually attach the session to a realm.

When the session then actually has attached, the onJoin() callback
fires. Now the session is ready.

Note: between onConnect() and onJoin() there are authentication related
callbacks.

Hmmm, I see, thanks for the explanation. FWIW, my class that extends ApplicationSession logs messages inside the onJoin and onConnect, and neither get called.

So, does anyone see something obvious I could be doing wrong? Any idea

why my onJoin() method is never called?

Could you modify your config for

               "url": "ws://[127.0.0.1:8080/ws](http://127.0.0.1:8080/ws)",

               "debug": true

and send us log output?

So I have modified the config to do the logging you requested, and here is the result: (Note that log entries beginning with "***** " are coming from my class that extends ApplicationSession, so I know the Python path is correct and my class is getting constructed)

scott@solaris:~/Documents/crossbar-tests/pvtest$ crossbar -d start

2014-08-26 15:10:50-0600 [Controller 10367] Log opened.

2014-08-26 15:10:50-0600 [Controller 10367] ============================== Crossbar.io ==============================

2014-08-26 15:10:50-0600 [Controller 10367] Crossbar.io 0.9.7-5 starting

2014-08-26 15:10:50-0600 [Controller 10367] Automatically choosing optimal Twisted reactor

2014-08-26 15:10:52-0600 [Controller 10367] Running Twisted reactor twisted.internet.epollreactor.EPollReactor

2014-08-26 15:10:52-0600 [Controller 10367] Running on CPython using EPollReactor reactor

2014-08-26 15:10:52-0600 [Controller 10367] Starting from node directory /home/scott/Documents/crossbar-tests/pvtest/.crossbar

2014-08-26 15:10:52-0600 [Controller 10367] Starting from local configuration ‘/home/scott/Documents/crossbar-tests/pvtest/.crossbar/config.json’

2014-08-26 15:10:52-0600 [Controller 10367] No WAMPlets detected in enviroment.

2014-08-26 15:10:52-0600 [Controller 10367] Starting Router with ID ‘worker1’ …

2014-08-26 15:10:53-0600 [Router 10376] Log opened.

2014-08-26 15:10:54-0600 [Router 10376] Running under CPython using EPollReactor reactor

2014-08-26 15:10:55-0600 [Router 10376] Entering event loop …

2014-08-26 15:10:55-0600 [Controller 10367] Router with ID ‘worker1’ and PID 10376 started

2014-08-26 15:10:55-0600 [Controller 10367] Router ‘worker1’: PYTHONPATH extended

2014-08-26 15:10:55-0600 [Controller 10367] Router ‘worker1’: realm ‘realm1’ started

2014-08-26 15:10:55-0600 [Controller 10367] Router ‘worker1’: role ‘role1’ started on realm ‘realm1’

2014-08-26 15:10:55-0600 [Router 10376] Site starting on 8080

2014-08-26 15:10:55-0600 [Controller 10367] Router ‘worker1’: transport ‘transport1’ started

2014-08-26 15:10:55-0600 [Controller 10367] Starting Container with ID ‘worker2’ …

2014-08-26 15:10:55-0600 [Container 10381] Log opened.

2014-08-26 15:10:57-0600 [Container 10381] Running under CPython using EPollReactor reactor

2014-08-26 15:10:57-0600 [Container 10381] Entering event loop …

2014-08-26 15:10:57-0600 [Controller 10367] Container with ID ‘worker2’ and PID 10381 started

2014-08-26 15:10:57-0600 [Controller 10367] Container ‘worker2’: PYTHONPATH extended

2014-08-26 15:11:05-0600 [Container 10381] [(‘debug’, True, ‘CrossbarWampWebSocketClientFactory’),

2014-08-26 15:11:05-0600 [Container 10381] (‘debugCodePaths’, False, ‘CrossbarWampWebSocketClientFactory’),

2014-08-26 15:11:05-0600 [Container 10381] (‘logOctets’, True, ‘CrossbarWampWebSocketClientFactory’),

2014-08-26 15:11:05-0600 [Container 10381] (‘logFrames’, True, ‘CrossbarWampWebSocketClientFactory’),

2014-08-26 15:11:05-0600 [Container 10381] (‘trackTimings’, False, ‘CrossbarWampWebSocketClientFactory’),

2014-08-26 15:11:05-0600 [Container 10381] (‘allowHixie76’, False, ‘CrossbarWampWebSocketClientFactory’),

2014-08-26 15:11:05-0600 [Container 10381] (‘utf8validateIncoming’, True, ‘CrossbarWampWebSocketClientFactory’),

2014-08-26 15:11:05-0600 [Container 10381] (‘applyMask’, True, ‘CrossbarWampWebSocketClientFactory’),

2014-08-26 15:11:05-0600 [Container 10381] (‘maxFramePayloadSize’, 0, ‘CrossbarWampWebSocketClientFactory’),

2014-08-26 15:11:05-0600 [Container 10381] (‘maxMessagePayloadSize’, 0, ‘CrossbarWampWebSocketClientFactory’),

2014-08-26 15:11:05-0600 [Container 10381] (‘autoFragmentSize’, 0, ‘CrossbarWampWebSocketClientFactory’),

2014-08-26 15:11:05-0600 [Container 10381] (‘failByDrop’, True, ‘CrossbarWampWebSocketClientFactory’),

2014-08-26 15:11:05-0600 [Container 10381] (‘echoCloseCodeReason’, False, ‘CrossbarWampWebSocketClientFactory’),

2014-08-26 15:11:05-0600 [Container 10381] (‘openHandshakeTimeout’, 5, ‘CrossbarWampWebSocketClientFactory’),

2014-08-26 15:11:05-0600 [Container 10381] (‘closeHandshakeTimeout’, 1, ‘CrossbarWampWebSocketClientFactory’),

2014-08-26 15:11:05-0600 [Container 10381] (‘tcpNoDelay’, True, ‘CrossbarWampWebSocketClientFactory’),

2014-08-26 15:11:05-0600 [Container 10381] (‘autoPingInterval’, 0, ‘CrossbarWampWebSocketClientFactory’),

2014-08-26 15:11:05-0600 [Container 10381] (‘autoPingTimeout’, 0, ‘CrossbarWampWebSocketClientFactory’),

2014-08-26 15:11:05-0600 [Container 10381] (‘autoPingSize’, 4, ‘CrossbarWampWebSocketClientFactory’),

2014-08-26 15:11:05-0600 [Container 10381] (‘version’, 18, ‘CrossbarWampWebSocketClientFactory’),

2014-08-26 15:11:05-0600 [Container 10381] (‘acceptMaskedServerFrames’, False, ‘CrossbarWampWebSocketClientFactory’),

2014-08-26 15:11:05-0600 [Container 10381] (‘maskClientFrames’, True, ‘CrossbarWampWebSocketClientFactory’),

2014-08-26 15:11:05-0600 [Container 10381] (‘serverConnectionDropTimeout’, 1, ‘CrossbarWampWebSocketClientFactory’),

2014-08-26 15:11:05-0600 [Container 10381] (‘perMessageCompressionOffers’, [], ‘CrossbarWampWebSocketClientFactory’),

2014-08-26 15:11:05-0600 [Container 10381] (‘perMessageCompressionAccept’,

2014-08-26 15:11:05-0600 [Container 10381] <function at 0x7fe70fe90f50>,

2014-08-26 15:11:05-0600 [Container 10381] ‘CrossbarWampWebSocketClientFactory’)]

2014-08-26 15:11:05-0600 [Container 10381] connection to 127.0.0.1:8080 established

2014-08-26 15:11:05-0600 [Container 10381] TX Octets to 127.0.0.1:8080 : sync = False, octets = 474554202f777320485454502f312e310d0a557365722d4167656e743a204175746f6261686e507974686f6e2f302e382e31340d0a486f73743a203132372e302e302e313a383038300d0a557067726164653a20576562536f636b65740d0a436f6e6e656374696f6e3a20557067726164650d0a507261676d613a206e6f2d63616368650d0a43616368652d436f6e74726f6c3a206e6f2d63616368650d0a5365632d576562536f636b65742d4b65793a206a715439307544457956776b534a6b5362644b4268773d3d0d0a5365632d576562536f636b65742d50726f746f636f6c3a2077616d702e322e6d73677061636b2e626174636865642c77616d702e322e6d73677061636b2c77616d702e322e6a736f6e2e626174636865642c77616d702e322e6a736f6e0d0a5365632d576562536f636b65742d56657273696f6e3a2031330d0a0d0a

2014-08-26 15:11:05-0600 [Container 10381] GET /ws HTTP/1.1

2014-08-26 15:11:05-0600 [Container 10381] User-Agent: AutobahnPython/0.8.14

2014-08-26 15:11:05-0600 [Container 10381] Host: 127.0.0.1:8080

2014-08-26 15:11:05-0600 [Container 10381] Upgrade: WebSocket

2014-08-26 15:11:05-0600 [Container 10381] Connection: Upgrade

2014-08-26 15:11:05-0600 [Container 10381] Pragma: no-cache

2014-08-26 15:11:05-0600 [Container 10381] Cache-Control: no-cache

2014-08-26 15:11:05-0600 [Container 10381] Sec-WebSocket-Key: jqT90uDEyVwkSJkSbdKBhw==

2014-08-26 15:11:05-0600 [Container 10381] Sec-WebSocket-Protocol: wamp.2.msgpack.batched,wamp.2.msgpack,wamp.2.json.batched,wamp.2.json

2014-08-26 15:11:05-0600 [Container 10381] Sec-WebSocket-Version: 13

2014-08-26 15:11:05-0600 [Container 10381] RX Octets from 127.0.0.1:8080 : octets = 485454502f312e312031303120537769746368696e672050726f746f636f6c730d0a5365727665723a2043726f73736261722f302e392e372d350d0a557067726164653a20576562536f636b65740d0a436f6e6e656374696f6e3a20557067726164650d0a5365632d576562536f636b65742d50726f746f636f6c3a2077616d702e322e6d73677061636b2e626174636865640d0a5365632d576562536f636b65742d4163636570743a206959774472486d69684b554d5062683166584c6a4c754c61564d413d0d0a0d0a

2014-08-26 15:11:05-0600 [Container 10381] received HTTP response:

2014-08-26 15:11:05-0600 [Container 10381] HTTP/1.1 101 Switching Protocols

2014-08-26 15:11:05-0600 [Container 10381] Server: Crossbar/0.9.7-5

2014-08-26 15:11:05-0600 [Container 10381] Upgrade: WebSocket

2014-08-26 15:11:05-0600 [Container 10381] Connection: Upgrade

2014-08-26 15:11:05-0600 [Container 10381] Sec-WebSocket-Protocol: wamp.2.msgpack.batched

2014-08-26 15:11:05-0600 [Container 10381] Sec-WebSocket-Accept: iYwDrHmihKUMPbh1fXLjLuLaVMA=

2014-08-26 15:11:05-0600 [Container 10381] received HTTP status line in opening handshake : HTTP/1.1 101 Switching Protocols

2014-08-26 15:11:05-0600 [Container 10381] received HTTP headers in opening handshake : {u’connection’: u’Upgrade’, u’upgrade’: u’WebSocket’, u’sec-websocket-protocol’: u’wamp.2.msgpack.batched’, u’sec-websocket-accept’: u’iYwDrHmihKUMPbh1fXLjLuLaVMA=’, u’server’: u’Crossbar/0.9.7-5’}

2014-08-26 15:11:05-0600 [Container 10381] ***** Inside ServerProtocol constructor

2014-08-26 15:11:05-0600 [Container 10381] ***** Adding protocol to be registered later: <class ‘paraview.web.protocols.ParaViewWebStartupRemoteConnection’>

2014-08-26 15:11:05-0600 [Container 10381] ***** Adding protocol to be registered later: <class ‘paraview.web.protocols.ParaViewWebStartupPluginLoader’>

2014-08-26 15:11:05-0600 [Container 10381] ***** Adding protocol to be registered later: <class ‘paraview.web.protocols.ParaViewWebStateLoader’>

2014-08-26 15:11:05-0600 [Container 10381] ***** Adding protocol to be registered later: <class ‘paraview.web.protocols.ParaViewWebFileListing’>

2014-08-26 15:11:05-0600 [Controller 10367] Container ‘worker2’: component ‘component1’ started

2014-08-26 15:11:05-0600 [Container 10381] ***** Adding protocol to be registered later: <class ‘paraview.web.protocols.ParaViewWebProxyManager’>

2014-08-26 15:11:05-0600 [Container 10381] ***** Adding protocol to be registered later: <class ‘paraview.web.protocols.ParaViewWebColorManager’>

2014-08-26 15:11:05-0600 [Container 10381] ***** Adding protocol to be registered later: <class ‘paraview.web.protocols.ParaViewWebMouseHandler’>

2014-08-26 15:11:05-0600 [Container 10381] ***** Adding protocol to be registered later: <class ‘paraview.web.protocols.ParaViewWebViewPort’>

2014-08-26 15:11:05-0600 [Container 10381] ***** Adding protocol to be registered later: <class ‘paraview.web.protocols.ParaViewWebViewPortImageDelivery’>

2014-08-26 15:11:05-0600 [Container 10381] ***** Adding protocol to be registered later: <class ‘paraview.web.protocols.ParaViewWebViewPortGeometryDelivery’>

2014-08-26 15:11:05-0600 [Container 10381] ***** Adding protocol to be registered later: <class ‘paraview.web.protocols.ParaViewWebTimeHandler’>

2014-08-26 15:11:05-0600 [Container 10381] ***** Adding protocol to be registered later: <class ‘paraview.web.protocols.ParaViewWebSelectionHandler’>

2014-08-26 15:11:05-0600 [Container 10381] ***** Adding protocol to be registered later: <class ‘paraview.web.protocols.ParaViewWebWidgetManager’>

2014-08-26 15:11:05-0600 [Container 10381] connection to 127.0.0.1:8080 lost

For completeness, here is the html I’m using to connect from the client side, though I don’t think I’m quite getting that far yet :slight_smile: Though it connects, it is unable to call the rpc method, which makes sense, because those methods are registered in my onJoin() method, which isn’t getting called.

  <h1>Hello WAMP</h1>

  <p>Open JavaScript console to watch output.</p>

  <script>AUTOBAHN_DEBUG = true;</script>

  <script src="ext/core/autobahn.min.js"></script>

  <script>

     // the WAMP connection to the Router

     //

     var connection = new autobahn.Connection({

        url: "ws://127.0.0.1:8080/ws",

        realm: "vtkweb"

     });

     // fired when connection is established and session attached

     //

     connection.onopen = function (session, details) {

        console.log("Connected");

        session.call('file.server.directory.list').then(

            function(res) {

                console.log("Successfully called rpc method:");

                console.log(obj);

            },

            function(err) {

                console.log("Error calling pv.files.list:");

                console.log(err);

            });

     };

     // fired when connection was lost (or could not be established)

     //

     connection.onclose = function (reason, details) {

        console.log("Connection lost: " + reason);

     }

     // now actually open the connection

     //

     connection.open();

  </script>

The console output from this html is:

AutobahnJS debug enabled autobahn.min.js:20

Connected (index):20

Error calling pv.files.list: (index):28

d {error: “wamp.error.no_such_procedure”, args: Array[1], kwargs: Object}

  1. args: Array[1]
  2. 0: “no procedure ‘file.server.directory.list’ registered”
  3. length: 1
  4. proto: Array[0]
  5. error: “wamp.error.no_such_procedure”
  6. kwargs: Object
  7. proto: Object

Additionally, here is my complete, unaltered config file (I don’t mind if any of my paths or file names are visible):

{

“controller”: {

},

“workers”: [

{

“type”: “router”,

“options”: {

“pythonpath”: ["…"]

},

“realms”: [

{

“name”: “vtkweb”,

“roles”: [

{

“name”: “anonymous”,

“permissions”: [

{

“uri”: “*”,

“publish”: true,

“subscribe”: true,

“call”: true,

“register”: true

}

]

}

]

}

],

“transports”: [

{

“type”: “web”,

“endpoint”: {

“type”: “tcp”,

“port”: 8080

},

“paths”: {

“/”: {

“type”: “static”,

“directory”: “/home/scott/projects/ParaView/build-make-debug/www”

},

“ws”: {

“type”: “websocket”

}

}

}

]

},

{

“type”: “container”,

“options”: {

“pythonpath”: ["/home/scott/projects/ParaView/build-make-debug/lib/site-packages","/home/scott/projects/ParaView/build-make-debug/lib"]

},

“components”: [

{

“type”: “class”,

“classname”: “paraview.web.pv_web_visualizer._VisualizerServer”,

“realm”: “vtkweb”,

“transport”: {

“type”: “websocket”,

“endpoint”: {

“type”: “tcp”,

“host”: “127.0.0.1”,

“port”: 8080

},

“url”: “ws://127.0.0.1:8080/ws”,

“debug”: true

}

}

]

}

]

}

Thanks again!

Scott

···

On Saturday, August 23, 2014 5:50:18 AM UTC-6, Tobias Oberstein wrote:

Thanks!

Scott

You received this message because you are subscribed to the Google

Groups “Autobahn” group.

To unsubscribe from this group and stop receiving emails from it, send

an email to autobahnws+...@googlegroups.com

mailto:autobahnws+unsub...@googlegroups.com.

To post to this group, send email to auto...@googlegroups.com

mailto:autob...@googlegroups.com.

To view this discussion on the web visit

https://groups.google.com/d/msgid/autobahnws/CAPiw4fCNgnQh0TSUT1P_sgWYHaj0oo%3D8_gGZrSQvki5dDadAnw%40mail.gmail.com

<https://groups.google.com/d/msgid/autobahnws/CAPiw4fCNgnQh0TSUT1P_sgWYHaj0oo%3D8_gGZrSQvki5dDadAnw%40mail.gmail.com?utm_medium=email&utm_source=footer>.

For more options, visit https://groups.google.com/d/optout.

0 Likes

#4

Hi Scott,

Hi Tobias,

    Sorry to take so long to respond, I usually see an email in my
inbox, but this time I didn't. I'm glad I finally came back to the
forum to check! Anyway, thanks for responding so quickly :slight_smile:

Don't worry: I still need to respond to your other mail also (rgd. auth etc). I _will_. Was just overwhelmed again with stuff.

I hope you have patience with Crossbar.io and getting your existing app hosted/running there. As you likely already recognized, this is still bleeding edge stuff. Needs to stabilize a litte. Don't go to production today;)

    A component connects to a router over a WAMP transport. When the
    transport is established, the onConnect() callback on your
    ApplicationSession fires. The default implementation of onConnect()
    then
    calls join() to actually attach the session to a realm.

    When the session then actually has attached, the onJoin() callback
    fires. Now the session is ready.

    Note: between onConnect() and onJoin() there are authentication related
    callbacks.

Hmmm, I see, thanks for the explanation. FWIW, my class that extends
ApplicationSession logs messages inside the onJoin and onConnect, and
neither get called.

This likely means the establishment of WAMP transport itself already fails.

So I have modified the config to do the logging you requested, and here
is the result: (Note that log entries beginning with "***** " are
coming from my class that extends ApplicationSession, so I know the
Python path is correct and my class is getting constructed)

Good: one source of error eliminated.

2014-08-26 15:11:05-0600 [Container 10381] connection to
127.0.0.1:8080 lost

This is bad.

The WebSocket connection is established, but before the WAMP session has attached to the Router realm, it fails.

For completeness, here is the html I'm using to connect from the client
side, though I don't think I'm quite getting that far yet :slight_smile: Though it
connects, it is unable to call the rpc method, which makes sense,
because those methods are registered in my onJoin() method, which isn't
getting called.

Yes. That's a consequence of the Callee component above not actually being attached to the Router realm.

Could you please try the attached config with your CB?

This is running the app component "side-by-side" inside the Router worker. This does away with any actual transport .. might help finding out what's going on. If it doesn't work, please attach log output

Cheers,
/Tobias

config.json (1.65 KB)

···

Am 26.08.2014 23:18, schrieb Scott Wittenburg:

0 Likes

#5

Hi Tobias,

Thanks for providing such great support! I feel you’re going above and beyond here, giving us specific configuration tips, checking our log files and such. I really appreciate it! Responses inline below…

Hi Scott,

Hi Tobias,

Sorry to take so long to respond, I usually see an email in my

inbox, but this time I didn’t. I’m glad I finally came back to the

forum to check! Anyway, thanks for responding so quickly :slight_smile:

Don’t worry: I still need to respond to your other mail also (rgd. auth
etc). I will. Was just overwhelmed again with stuff.

No worries, I completely understand. And anyway, I feel you’ve been very responsive in spite of how busy you must be.

I hope you have patience with Crossbar.io and getting your existing app
hosted/running there. As you likely already recognized, this is still
bleeding edge stuff. Needs to stabilize a litte. Don’t go to production
today;)

Nope, we’re not going to production right away :slight_smile: I’m enjoying learning about new technology, and just kind of pursuing this tangentially for now. But it definitely has a lot of capabilities that seem very promising for us.

A component connects to a router over a WAMP transport. When the
transport is established, the onConnect() callback on your
ApplicationSession fires. The default implementation of onConnect()
then
calls join() to actually attach the session to a realm.
When the session then actually has attached, the onJoin() callback
fires. Now the session is ready.
Note: between onConnect() and onJoin() there are authentication related
callbacks.

Hmmm, I see, thanks for the explanation. FWIW, my class that extends

ApplicationSession logs messages inside the onJoin and onConnect, and

neither get called.

This likely means the establishment of WAMP transport itself already fails.

Interesting. This may have nothing to do with it, but I was wondering if there could be a problem with the fact that our ApplicationSession object is using one version of Autobahn python, while crossbar.io is starting the router and probably using a different version. Could there be an issue here?

So I have modified the config to do the logging you requested, and here

is the result: (Note that log entries beginning with "***** " are

coming from my class that extends ApplicationSession, so I know the

Python path is correct and my class is getting constructed)

Good: one source of error eliminated.

2014-08-26 15:11:05-0600 [Container 10381] connection to

127.0.0.1:8080 lost

This is bad.

The WebSocket connection is established, but before the WAMP session has
attached to the Router realm, it fails.

I need to go back to the docs and read about how the realms fit into the architecture.

For completeness, here is the html I’m using to connect from the client

side, though I don’t think I’m quite getting that far yet :slight_smile: Though it

connects, it is unable to call the rpc method, which makes sense,

because those methods are registered in my onJoin() method, which isn’t

getting called.

Yes. That’s a consequence of the Callee component above not actually
being attached to the Router realm.

Could you please try the attached config with your CB?

This is running the app component “side-by-side” inside the Router
worker. This does away with any actual transport … might help finding
out what’s going on. If it doesn’t work, please attach log output

Ok, so I ran it again with the new “side-by-side” configuration. For one thing, it’s just cool to see how many different scenarios will be supported, and to see via example how many different ways there are of getting things to talk to each other. But here’s the log output after running the application inside the router:

scott@solaris:~/Documents/crossbar-tests/pvtest$ crossbar -d start

2014-08-27 10:43:05-0600 [Controller 26907] Log opened.

2014-08-27 10:43:05-0600 [Controller 26907] ============================== Crossbar.io ==============================

2014-08-27 10:43:05-0600 [Controller 26907] Crossbar.io 0.9.7-5 starting

2014-08-27 10:43:05-0600 [Controller 26907] Automatically choosing optimal Twisted reactor

2014-08-27 10:43:06-0600 [Controller 26907] Running Twisted reactor twisted.internet.epollreactor.EPollReactor

2014-08-27 10:43:06-0600 [Controller 26907] Running on CPython using EPollReactor reactor

2014-08-27 10:43:06-0600 [Controller 26907] Starting from node directory /home/scott/Documents/crossbar-tests/pvtest/.crossbar

2014-08-27 10:43:07-0600 [Controller 26907] Starting from local configuration ‘/home/scott/Documents/crossbar-tests/pvtest/.crossbar/config.json’

2014-08-27 10:43:07-0600 [Controller 26907] No WAMPlets detected in enviroment.

2014-08-27 10:43:07-0600 [Controller 26907] Starting Router with ID ‘worker1’ …

2014-08-27 10:43:07-0600 [Router 26918] Log opened.

2014-08-27 10:43:09-0600 [Router 26918] Running under CPython using EPollReactor reactor

2014-08-27 10:43:09-0600 [Router 26918] Entering event loop …

2014-08-27 10:43:09-0600 [Controller 26907] Router with ID ‘worker1’ and PID 26918 started

2014-08-27 10:43:09-0600 [Controller 26907] Router ‘worker1’: PYTHONPATH extended

2014-08-27 10:43:09-0600 [Controller 26907] Router ‘worker1’: realm ‘realm1’ started

2014-08-27 10:43:09-0600 [Controller 26907] Router ‘worker1’: role ‘role1’ started on realm ‘realm1’

2014-08-27 10:43:17-0600 [Router 26918] ***** Inside ServerProtocol constructor

2014-08-27 10:43:17-0600 [Router 26918] ***** Adding protocol to be registered later: <class ‘paraview.web.protocols.ParaViewWebStartupRemoteConnection’>

2014-08-27 10:43:17-0600 [Router 26918] ***** Adding protocol to be registered later: <class ‘paraview.web.protocols.ParaViewWebStartupPluginLoader’>

2014-08-27 10:43:17-0600 [Router 26918] ***** Adding protocol to be registered later: <class ‘paraview.web.protocols.ParaViewWebStateLoader’>

2014-08-27 10:43:17-0600 [Router 26918] ***** Adding protocol to be registered later: <class ‘paraview.web.protocols.ParaViewWebFileListing’>

2014-08-27 10:43:17-0600 [Router 26918] ***** Adding protocol to be registered later: <class ‘paraview.web.protocols.ParaViewWebProxyManager’>

2014-08-27 10:43:17-0600 [Router 26918] ***** Adding protocol to be registered later: <class ‘paraview.web.protocols.ParaViewWebColorManager’>

2014-08-27 10:43:17-0600 [Router 26918] ***** Adding protocol to be registered later: <class ‘paraview.web.protocols.ParaViewWebMouseHandler’>

2014-08-27 10:43:17-0600 [Router 26918] ***** Adding protocol to be registered later: <class ‘paraview.web.protocols.ParaViewWebViewPort’>

2014-08-27 10:43:17-0600 [Router 26918] ***** Adding protocol to be registered later: <class ‘paraview.web.protocols.ParaViewWebViewPortImageDelivery’>

2014-08-27 10:43:17-0600 [Router 26918] ***** Adding protocol to be registered later: <class ‘paraview.web.protocols.ParaViewWebViewPortGeometryDelivery’>

2014-08-27 10:43:17-0600 [Router 26918] ***** Adding protocol to be registered later: <class ‘paraview.web.protocols.ParaViewWebTimeHandler’>

2014-08-27 10:43:17-0600 [Router 26918] ***** Adding protocol to be registered later: <class ‘paraview.web.protocols.ParaViewWebSelectionHandler’>

2014-08-27 10:43:17-0600 [Router 26918] ***** Adding protocol to be registered later: <class ‘paraview.web.protocols.ParaViewWebWidgetManager’>

2014-08-27 10:43:17-0600 [Controller 26907] Traceback (most recent call last):

2014-08-27 10:43:17-0600 [Controller 26907] File “/usr/local/lib/python2.7/dist-packages/crossbar/controller/node.py”, line 187, in run_node_config

2014-08-27 10:43:17-0600 [Controller 26907] yield self._run_node_config(config)

2014-08-27 10:43:17-0600 [Controller 26907] ApplicationError: ApplicationError(‘crossbar.error.class_import_failed’, args = (“ComponentConfig instance has no attribute ‘updateKey’”,), kwargs = {})

2014-08-27 10:43:17-0600 [Controller 26907] Main loop terminated.

scott@solaris:~/Documents/crossbar-tests/pvtest$

I hope this can give you some insight to what I might be doing wrong. Thanks again for all your help Tobias, you guys are doing a great job!

Cheers,

Scott

···

On Wednesday, August 27, 2014 8:25:23 AM UTC-6, Tobias Oberstein wrote:

Am 26.08.2014 23:18, schrieb Scott Wittenburg:

Cheers,

/Tobias

0 Likes

#6

Interesting. This may have nothing to do with it, but I was wondering if there could

> be a problem with the fact that our ApplicationSession object is using one version of
> Autobahn python, while crossbar.io is starting the router and probably using a different
> version. Could there be an issue here?

Oh. Yes. At least now since we try running the compontent side-by-side.

If you can, could you try/assure that only 1 Python version and 1 AutobahnPython is used by both?

2014-08-27 10:43:17-0600 [Controller 26907] ApplicationError:
ApplicationError('crossbar.error.class_import_failed', args =
("ComponentConfig instance has no attribute 'updateKey'",), kwargs = {})

This is absolutely strange. There is no string "updateKey" in the whole AutobahnPython and Crossbar source code!

The class ComponentConfig is trivial:

https://github.com/tavendo/AutobahnPython/blob/master/autobahn/autobahn/wamp/types.py#L44

I tried to Google around .. came about this

https://www.google.com/search?q=kitware+"updateKey"&ie=utf-8&oe=utf-8&aq=t&rls=org.mozilla:de:official&client=firefox-a&channel=sb

??

Unfortunately, the file does not exist anymore .. I only see part of the Google cache:

vtkWebProtocols. def updateSecret(self, newSecret): if self.authdb: self.authdb.updateKey('vtkweb', newSecret). @exportRpc("application.exit"). def exit(self):.

Don't know if that is related ..

Can you post part of your ApplicationSession derived class? I mean in particular the constructor and relevant code lines where you call the base constructor?

This is strange ..

/Tobias

0 Likes

#7

Interesting. This may have nothing to do with it, but I was wondering if there could

be a problem with the fact that our ApplicationSession object is
using one version of

Autobahn python, while crossbar.io is starting the router and
probably using a different

version. Could there be an issue here?

Oh. Yes. At least now since we try running the compontent side-by-side.

If you can, could you try/assure that only 1 Python version and 1
AutobahnPython is used by both?

Yes, it seems that when I pip installed crossbar.io, my system python now has access to all the autobahn and twisted classes we put into our site-packages folder. So by renaming those site-packages directories, I believe I have forced my ApplicationSession class to use the same version of autobahn/twisted used by crossbar. And I get the same error, which could make sense, because we are currently supplying very recent versions of autobahn/twisted with paraview/vtk.

2014-08-27 10:43:17-0600 [Controller 26907] ApplicationError:

ApplicationError(‘crossbar.error.class_import_failed’, args =

(“ComponentConfig instance has no attribute ‘updateKey’”,), kwargs = {})

This is absolutely strange. There is no string “updateKey” in the whole
AutobahnPython and Crossbar source code!

The class ComponentConfig is trivial:

https://github.com/tavendo/AutobahnPython/blob/master/autobahn/autobahn/wamp/types.py#L44

I tried to Google around … came about this

https://www.google.com/search?q=kitware+%22updateKey%22&ie=utf-8&oe=utf-8&aq=t&rls=org.mozilla:de:official&client=firefox-a&channel=sb

??

Unfortunately, the file does not exist anymore … I only see part of the
Google cache:

vtkWebProtocols. def updateSecret(self, newSecret): if self.authdb:
self.authdb.updateKey(‘vtkweb’, newSecret).
@exportRpc(“application.exit”). def exit(self):.

Don’t know if that is related …

Can you post part of your ApplicationSession derived class? I mean in
particular the constructor and relevant code lines where you call the
base constructor?

This is strange …

Ok, yes, this is strange. We do have such a string in our source code, as you will see below. This is probably the time to explain some fancy stuff we’re doing with our use of Autobahn. I’m going to try to paste in here three stripped down snippets which hopefully allow you to see how things work, but you can always see exactly what we’re doing by looking at our git repo, here:

http://www.paraview.org/gitweb?p=ParaView.git;a=tree

But stuff is kind of spread around in there, so don’t feel you have to spend time browsing around. I’m just putting it out there in case…

So the basic idea is we try to allow people to come up with their own ApplicationSessions which can compose any of the “protocols” we have already defined (not to be confused with the Autobahn protocol package). These “protocols” are classes which can export any number of rpc methods each, and by mixing and matching them, people should be able to come up with their own custom server application which exports exactly the rpc methods they need.

Our class that extends ApplicationSession, “ServerProtocol”, can be extended by anyone who wants to write their own server application:

class ServerProtocol(ApplicationSession):

"""

Defines the core server protocol for vtkWeb. Adds support to

marshall/unmarshall RPC callbacks that involve ServerManager proxies as

arguments or return values.

Applications typically don't use this class directly, since it doesn't

register any RPC callbacks that are required for basic web-applications with

interactive visualizations. For that, use vtkWebServerProtocol.

"""

def __init__(self, authdb=None):

    log.msg("   *****   Inside ServerProtocol constructor", logLevel=logging.DEBUG)

    ApplicationSession.__init__(self, types.ComponentConfig(realm = "vtkweb"))

    self.vtkWebProtocols = []

    self.authdb = authdb

    self.Application = self.initApplication()

    self.initialize()

def initialize(self):

    """

    Let the sub class define what they need to do to properly initialize

    themselves.

    """

    pass

def initApplication(self):

    """

    Let subclass optionally initialize a custom application in lieu

    of the default vtkWebApplication.

    """

    global application

    if not application:

        application = vtkWebApplication()

    return application

def onConnect(self):

    log.msg("   *****   Inside onConnect method", logLevel=logging.DEBUG)

    ApplicationSession.onConnect(self)

def onJoin(self, details):

    log.msg("   *****   Inside onJoin method", logLevel=logging.DEBUG)

    ApplicationSession.onJoin(self, details)

    self.register(self)

    for protocol in self.vtkWebProtocols:

        m = "   *****   Registering protocol: %s" % (str(protocol.__class__))

        log.msg(m, logLevel=logging.DEBUG)

        self.register(protocol)

def setApplication(self, application):

    self.Application = application

def registerVtkWebProtocol(self, protocol):

    m = "   *****   Adding protocol to be registered later: %s" % (str(protocol.__class__))

    log.msg(m, logLevel=logging.DEBUG)

    protocol.setApplication(self.Application)

    self.vtkWebProtocols.append(protocol)

def getVtkWebProtocols(self):

    return self.vtkWebProtocols

def updateSecret(self, newSecret):

    if self.authdb:

        self.authdb.updateKey('vtkweb', newSecret)

@exportRpc("application.exit")

def exit(self):

    """RPC callback to exit"""

    reactor.stop()

A “Protocol” class that can export any number of rpc methods, we have a lot of these classes (btw, we have imported “register” as “exportRpc” in this module for our own convenience):

class ParaViewWebFileManager():

def __init__(self, defaultDirectoryToList):

    self.directory = defaultDirectoryToList

@exportRpc("pv.files.list")

def listFiles(self):

    return helper.listFiles(self.directory)

A class that extends that extends ServerProtocol and can now selectively compose any combination of rpc methods by instantiating some “Protocol” classes:

class BasicServer(ServerProtocol):

directoryToList = '/path/to/directory'

authKey = "vtkweb-secret"



def initialize(self):

    # Bring in the components this class needs

    self.registerVtkWebProtocol(ParaViewWebFileManager(BasicServer.directoryToList))

    # Update authentication key to use

    self.updateSecret(BasicServer.authKey)

This BasicServer is doing exactly the same thing as _VisualizerServer from my previous posts, I just stripped out most of it to try and avoid a lot of unnecessary confusion.

So maybe these snippets let you see how we may have broken your expected model of registering rpc methods. And you can see how the string updateKey is a function I intended to be calling on our AuthDb, something I explained in another thread, and which I had thought could be ignored in this case, since it should not be used at all. Though it is present in the ServerProtocol constructor with a default value of None, and that is where the ComponentConfig constructor is invoked.

In my snippets I have stripped out a lot of stuff (including all the import statements), in an attempt to just get across the key points. Please let me know if I was overzealous there.

Thanks again, sorry to be so noisy on the list :slight_smile:

···

On Wednesday, August 27, 2014 12:19:37 PM UTC-6, Tobias Oberstein wrote:

/Tobias

0 Likes

#8

Hi Scott,

> Ok, yes, this is strange. We do have such a string in our source code,

as you will see below. This is probably the time to explain some fancy
stuff we're doing with our use of Autobahn. I'm going to try to paste

From what I see below, yes, that is likely a source of problems;)

in here three stripped down snippets which hopefully allow you to see
how things work, but you can always see exactly what we're doing by
looking at our git repo, here:

http://www.paraview.org/gitweb?p=ParaView.git;a=tree

But stuff is kind of spread around in there, so don't feel you have to
spend time browsing around. I'm just putting it out there in case...

So the basic idea is we try to allow people to come up with their own
ApplicationSessions which can compose any of the "protocols" we have
already defined (not to be confused with the Autobahn protocol package).
  These "protocols" are classes which can export any number of rpc
methods each, and by mixing and matching them, people should be able to
come up with their own custom server application which exports exactly
the rpc methods they need.

Let's first get basic stuff working and come back to this later. I'm not sure I get what you want to do here ..

Our class that extends ApplicationSession, "ServerProtocol", can be
extended by anyone who wants to write their own server application:

class ServerProtocol(ApplicationSession):

     def __init__(self, authdb=None):
         ApplicationSession.__init__(self, types.ComponentConfig(realm =

This is the problem. I suspected this .. hence I asked about the constructor and call of base constructor;)

Crossbar.io will instantiate your ServerProtocol providing a ComponentConfig .. not something you expect in authdb.

This is part of the interface contract of ApplicationSession.

If you want to override the constructor of ApplicationSession, the correct way is:

def __init__(self, config):
    ApplicationSession.__init__(self, config)
    ## do other initialization stuff

You can't pass in authdb (whatever that is). How would Crossbar.io (or any other ApplicationSession driver) know how to construct that?

What you can do is pass in "extra" configuration (from JSON config), and by using that info, create the authdb thing inside __init__. Or later in onJoin.

     def initApplication(self):
         """
         Let subclass optionally initialize a custom application in lieu
         of the default vtkWebApplication.
         """
         global application

Bad, bad. "global" should be removed from the Python language;)

     @exportRpc("application.exit")
     def exit(self):
         """RPC callback to exit"""
         reactor.stop()

A "Protocol" class that can export any number of rpc methods, we have a
lot of these classes (btw, we have imported "register" as "exportRpc" in
this module for our own convenience):

This is confusing, since it was called exportRpc only in the old AutobahnPython WAMPv1 ..

So maybe these snippets let you see how we may have broken your expected
model of registering rpc methods. And you can see how the string
updateKey is a function I intended to be calling on our AuthDb,
something I explained in another thread, and which I had thought could
be ignored in this case, since it should not be used at all. Though it
is present in the ServerProtocol constructor with a default value of
None, and that is where the ComponentConfig constructor is invoked.

The problem at hand is like above.

To give you advice on how to do better, I'd need to understand what you are actually trying to achieve - means, what's the end _goal_. In high level description.

Talking about the current code and reverse engineer your actual goals is time consuming. But I'm confident we find a "clean" way ..

Cheers,
/Tobias

0 Likes

#9

Hi Tobias,

Ok, overriding the ApplicationSession constructor the correct way has resolved all the problems I was seeing. Now both configurations seem to work fine, crossbar can run our existing server in either case, and our existing javascript client works with almost no changes, which is fantastic! Thanks for helping me figure this out, sorry I brought in too much information last time when all you needed was to see the constructor.

The one thing I had to change on the javascript client was to remove the authentication properties from the autobahn.Connection() constructor configuration object. Is there some simple way we can tell crossbar (via our config.json or some file on the side) about a single user name and password that the client can then use to connect via wampcra authentication?

Since you’re so helpful, you can look forward to some more of my questions on the list in the next few days :slight_smile: But I’m really excited to have things working so well already, and thank you for all the time you have spent so far!

Cheers,

Scott

···

On Wednesday, August 27, 2014 2:02:53 PM UTC-6, Tobias Oberstein wrote:

Hi Scott,

Ok, yes, this is strange. We do have such a string in our source code,

as you will see below. This is probably the time to explain some fancy

stuff we’re doing with our use of Autobahn. I’m going to try to paste

From what I see below, yes, that is likely a source of problems;)

in here three stripped down snippets which hopefully allow you to see

how things work, but you can always see exactly what we’re doing by

looking at our git repo, here:

http://www.paraview.org/gitweb?p=ParaView.git;a=tree

But stuff is kind of spread around in there, so don’t feel you have to

spend time browsing around. I’m just putting it out there in case…

So the basic idea is we try to allow people to come up with their own

ApplicationSessions which can compose any of the “protocols” we have

already defined (not to be confused with the Autobahn protocol package).

These “protocols” are classes which can export any number of rpc

methods each, and by mixing and matching them, people should be able to

come up with their own custom server application which exports exactly

the rpc methods they need.

Let’s first get basic stuff working and come back to this later. I’m not
sure I get what you want to do here …

Our class that extends ApplicationSession, “ServerProtocol”, can be

extended by anyone who wants to write their own server application:

class ServerProtocol(ApplicationSession):

 def __init__(self, authdb=None):
     ApplicationSession.__init__(self, types.ComponentConfig(realm =

This is the problem. I suspected this … hence I asked about the
constructor and call of base constructor;)

Crossbar.io will instantiate your ServerProtocol providing a
ComponentConfig … not something you expect in authdb.

This is part of the interface contract of ApplicationSession.

If you want to override the constructor of ApplicationSession, the
correct way is:

def init(self, config):

ApplicationSession.__init__(self, config)

## do other initialization stuff

You can’t pass in authdb (whatever that is). How would Crossbar.io (or
any other ApplicationSession driver) know how to construct that?

What you can do is pass in “extra” configuration (from JSON config), and
by using that info, create the authdb thing inside init. Or later in
onJoin.

 def initApplication(self):
     """
     Let subclass optionally initialize a custom application in lieu
     of the default vtkWebApplication.
     """
     global application

Bad, bad. “global” should be removed from the Python language;)

 @exportRpc("application.exit")
 def exit(self):
     """RPC callback to exit"""
     reactor.stop()

A “Protocol” class that can export any number of rpc methods, we have a

lot of these classes (btw, we have imported “register” as “exportRpc” in

this module for our own convenience):

This is confusing, since it was called exportRpc only in the old
AutobahnPython WAMPv1 …

So maybe these snippets let you see how we may have broken your expected

model of registering rpc methods. And you can see how the string

updateKey is a function I intended to be calling on our AuthDb,

something I explained in another thread, and which I had thought could

be ignored in this case, since it should not be used at all. Though it

is present in the ServerProtocol constructor with a default value of

None, and that is where the ComponentConfig constructor is invoked.

The problem at hand is like above.

To give you advice on how to do better, I’d need to understand what you
are actually trying to achieve - means, what’s the end goal. In high
level description.

Talking about the current code and reverse engineer your actual goals is
time consuming. But I’m confident we find a “clean” way …

Cheers,

/Tobias

0 Likes

#10

Hi Scott,

> Ok, overriding the ApplicationSession constructor the correct way

has resolved all the problems I was seeing. Now both configurations
seem to work fine, crossbar can run our existing server in either case,
and our existing javascript client works with almost no changes, which
is fantastic! Thanks for helping me figure this out, sorry I brought in

Great! I'm glad you got it working. Thank's for your patience!

Looking back at our conversation and what was needed to solve the problem, it's clear - again - that 2 areas that need improvement are:

- docs
- logging

I filed tickets for those:

https://github.com/crossbario/crossbar/issues/110
https://github.com/crossbario/crossbar/issues/111

too much information last time when all you needed was to see the
constructor.

np. better more than not enough ..

    The one thing I had to change on the javascript client was to remove
the authentication properties from the autobahn.Connection() constructor
configuration object. Is there some simple way we can tell crossbar
(via our config.json or some file on the side) about a single user name
and password that the client can then use to connect via wampcra
authentication?

There are still some bits left to hook WAMP-CRA into Crossbar .. I do that in the coming days and come back to you.

    Since you're so helpful, you can look forward to some more of my
questions on the list in the next few days :slight_smile: But I'm really excited

Yes, please!

to have things working so well already, and thank you for all the time
you have spent so far!

I am happy that you already see where Crossbar can bring benefits to your applications and systems. The ability for flexible component deployment - without changing a single line of app code - is one of those.

/Tobias

···

Cheers,
Scott

On Wednesday, August 27, 2014 2:02:53 PM UTC-6, Tobias Oberstein wrote:

    Hi Scott,

      > Ok, yes, this is strange. We do have such a string in our
    source code,
     > as you will see below. This is probably the time to explain some
    fancy
     > stuff we're doing with our use of Autobahn. I'm going to try to
    paste

      From what I see below, yes, that is likely a source of problems;)

     > in here three stripped down snippets which hopefully allow you to
    see
     > how things work, but you can always see exactly what we're doing by
     > looking at our git repo, here:
     >
     > http://www.paraview.org/gitweb?p=ParaView.git;a=tree
    <http://www.paraview.org/gitweb?p=ParaView.git;a=tree>
     >
     > But stuff is kind of spread around in there, so don't feel you
    have to
     > spend time browsing around. I'm just putting it out there in
    case...
     >
     > So the basic idea is we try to allow people to come up with their
    own
     > ApplicationSessions which can compose any of the "protocols" we have
     > already defined (not to be confused with the Autobahn protocol
    package).
     > These "protocols" are classes which can export any number of rpc
     > methods each, and by mixing and matching them, people should be
    able to
     > come up with their own custom server application which exports
    exactly
     > the rpc methods they need.

    Let's first get basic stuff working and come back to this later. I'm
    not
    sure I get what you want to do here ..

     >
     > Our class that extends ApplicationSession, "ServerProtocol", can be
     > extended by anyone who wants to write their own server application:
     >
     > class ServerProtocol(ApplicationSession):
     >
     > def __init__(self, authdb=None):
     > ApplicationSession.__init__(self,
    types.ComponentConfig(realm =

    This is the problem. I suspected this .. hence I asked about the
    constructor and call of base constructor;)

    Crossbar.io will instantiate your ServerProtocol providing a
    ComponentConfig .. not something you expect in authdb.

    This is part of the interface contract of ApplicationSession.

    If you want to override the constructor of ApplicationSession, the
    correct way is:

    def __init__(self, config):
         ApplicationSession.__init__(self, config)
         ## do other initialization stuff

    You can't pass in authdb (whatever that is). How would Crossbar.io (or
    any other ApplicationSession driver) know how to construct that?

    What you can do is pass in "extra" configuration (from JSON config),
    and
    by using that info, create the authdb thing inside __init__. Or
    later in
    onJoin.

     > def initApplication(self):
     > """
     > Let subclass optionally initialize a custom application
    in lieu
     > of the default vtkWebApplication.
     > """
     > global application

    Bad, bad. "global" should be removed from the Python language;)

     > @exportRpc("application.exit")
     > def exit(self):
     > """RPC callback to exit"""
     > reactor.stop()
     >
     > A "Protocol" class that can export any number of rpc methods, we
    have a
     > lot of these classes (btw, we have imported "register" as
    "exportRpc" in
     > this module for our own convenience):

    This is confusing, since it was called exportRpc only in the old
    AutobahnPython WAMPv1 ..

     > So maybe these snippets let you see how we may have broken your
    expected
     > model of registering rpc methods. And you can see how the string
     > updateKey is a function I intended to be calling on our AuthDb,
     > something I explained in another thread, and which I had thought
    could
     > be ignored in this case, since it should not be used at all.
      Though it
     > is present in the ServerProtocol constructor with a default value of
     > None, and that is where the ComponentConfig constructor is invoked.
     >

    The problem at hand is like above.

    To give you advice on how to do better, I'd need to understand what you
    are actually trying to achieve - means, what's the end _goal_. In high
    level description.

    Talking about the current code and reverse engineer your actual
    goals is
    time consuming. But I'm confident we find a "clean" way ..

    Cheers,
    /Tobias

--
You received this message because you are subscribed to the Google
Groups "Autobahn" group.
To unsubscribe from this group and stop receiving emails from it, send
an email to autobahnws+...@googlegroups.com
<mailto:autobahnws+...@googlegroups.com>.
To post to this group, send email to autob...@googlegroups.com
<mailto:autob...@googlegroups.com>.
To view this discussion on the web visit
https://groups.google.com/d/msgid/autobahnws/ad4bcafc-ece0-40d1-8d65-73e69ff81b3c%40googlegroups.com
<https://groups.google.com/d/msgid/autobahnws/ad4bcafc-ece0-40d1-8d65-73e69ff81b3c%40googlegroups.com?utm_medium=email&utm_source=footer>.
For more options, visit https://groups.google.com/d/optout.

0 Likes

#11

Hi Tobias,

Hi Scott,

Ok, overriding the ApplicationSession constructor the correct way

has resolved all the problems I was seeing. Now both configurations

seem to work fine, crossbar can run our existing server in either case,

and our existing javascript client works with almost no changes, which

is fantastic! Thanks for helping me figure this out, sorry I brought in

Great! I’m glad you got it working. Thank’s for your patience!

Looking back at our conversation and what was needed to solve the
problem, it’s clear - again - that 2 areas that need improvement are:

  • docs

  • logging

I filed tickets for those:

https://github.com/crossbario/crossbar/issues/110

https://github.com/crossbario/crossbar/issues/111

Sounds good, perhaps having those things would have helped me to figure out the problem without taking your time. But I feel I should have probably caught that ApplicationSession constructor problem on my own anyway… sheesh.

too much information last time when all you needed was to see the

constructor.

np. better more than not enough …

The one thing I had to change on the javascript client was to remove

the authentication properties from the autobahn.Connection() constructor

configuration object. Is there some simple way we can tell crossbar

(via our config.json or some file on the side) about a single user name

and password that the client can then use to connect via wampcra

authentication?

There are still some bits left to hook WAMP-CRA into Crossbar … I do
that in the coming days and come back to you.

Ok, great. For now, it seems that even if my javascript client requests wampcra authentication, if the server side isn’t configured with any authentication, the connection is allowed to be made. This is great for me at the current time, but is this the behavior you would expect?

Since you're so helpful, you can look forward to some more of my

questions on the list in the next few days :slight_smile: But I’m really excited

Yes, please!

to have things working so well already, and thank you for all the time

you have spent so far!

I am happy that you already see where Crossbar can bring benefits to
your applications and systems. The ability for flexible component
deployment - without changing a single line of app code - is one of those.

Yes, it’s pretty awesome! I was just fiddling around with my configs, and I got my application and router workers to run in separate crossbar nodes, which is so cool.

Thanks for being patient with me, Tobias, I really appreciate your help figuring out onJoin() problem!

Cheers,

Scott

···

On Thursday, August 28, 2014 1:54:49 AM UTC-6, Tobias Oberstein wrote:

/Tobias

Cheers,

Scott

On Wednesday, August 27, 2014 2:02:53 PM UTC-6, Tobias Oberstein wrote:

Hi Scott,
  > Ok, yes, this is strange.  We do have such a string in our
source code,
 > as you will see below.  This is probably the time to explain some
fancy
 > stuff we're doing with our use of Autobahn.  I'm going to try to
paste
  From what I see below, yes, that is likely a source of problems;)
 > in here three stripped down snippets which hopefully allow you to
see
 > how things work, but you can always see exactly what we're doing by
 > looking at our git repo, here:
 >
 > [http://www.paraview.org/gitweb?p=ParaView.git;a=tree](http://www.paraview.org/gitweb?p=ParaView.git;a=tree)
<[http://www.paraview.org/gitweb?p=ParaView.git;a=tree](http://www.paraview.org/gitweb?p=ParaView.git;a=tree)>
 >
 > But stuff is kind of spread around in there, so don't feel you
have to
 > spend time browsing around.  I'm just putting it out there in
case...
 >
 > So the basic idea is we try to allow people to come up with their
own
 > ApplicationSessions which can compose any of the "protocols" we have
 > already defined (not to be confused with the Autobahn protocol
package).
 >   These "protocols" are classes which can export any number of rpc
 > methods each, and by mixing and matching them, people should be
able to
 > come up with their own custom server application which exports
exactly
 > the rpc methods they need.
Let's first get basic stuff working and come back to this later. I'm
not
sure I get what you want to do here ..
 >
 > Our class that extends ApplicationSession, "ServerProtocol", can be
 > extended by anyone who wants to write their own server application:
 >
 > class ServerProtocol(ApplicationSession):
 >
 >      def __init__(self, authdb=None):
 >          ApplicationSession.__init__(self,
types.ComponentConfig(realm =
This is the problem. I suspected this .. hence I asked about the
constructor and call of base constructor;)
Crossbar.io will instantiate your ServerProtocol providing a
ComponentConfig .. not something you expect in authdb.
This is part of the interface contract of ApplicationSession.
If you want to override the constructor of ApplicationSession, the
correct way is:
def __init__(self, config):
     ApplicationSession.__init__(self, config)
     ## do other initialization stuff
You can't pass in authdb (whatever that is). How would Crossbar.io (or
any other ApplicationSession driver) know how to construct that?
What you can do is pass in "extra" configuration (from JSON config),
and
by using that info, create the authdb thing inside __init__. Or
later in
onJoin.
 >      def initApplication(self):
 >          """
 >          Let subclass optionally initialize a custom application
in lieu
 >          of the default vtkWebApplication.
 >          """
 >          global application
Bad, bad. "global" should be removed from the Python language;)
 >      @exportRpc("application.exit")
 >      def exit(self):
 >          """RPC callback to exit"""
 >          reactor.stop()
 >
 > A "Protocol" class that can export any number of rpc methods, we
have a
 > lot of these classes (btw, we have imported "register" as
"exportRpc" in
 > this module for our own convenience):
This is confusing, since it was called exportRpc only in the old
AutobahnPython WAMPv1 ..
 > So maybe these snippets let you see how we may have broken your
expected
 > model of registering rpc methods.  And you can see how the string
 > updateKey is a function I intended to be calling on our AuthDb,
 > something I explained in another thread, and which I had thought
could
 > be ignored in this case, since it should not be used at all.
  Though it
 > is present in the ServerProtocol constructor with a default value of
 > None, and that is where the ComponentConfig constructor is invoked.
 >
The problem at hand is like above.
To give you advice on how to do better, I'd need to understand what you
are actually trying to achieve - means, what's the end _goal_. In high
level description.
Talking about the current code and reverse engineer your actual
goals is
time consuming. But I'm confident we find a "clean" way ..
Cheers,
/Tobias

You received this message because you are subscribed to the Google

Groups “Autobahn” group.

To unsubscribe from this group and stop receiving emails from it, send

an email to autobahnws+...@googlegroups.com

mailto:autobahnws+unsub...@googlegroups.com.

To post to this group, send email to auto...@googlegroups.com

mailto:autob...@googlegroups.com.

To view this discussion on the web visit

https://groups.google.com/d/msgid/autobahnws/ad4bcafc-ece0-40d1-8d65-73e69ff81b3c%40googlegroups.com

<https://groups.google.com/d/msgid/autobahnws/ad4bcafc-ece0-40d1-8d65-73e69ff81b3c%40googlegroups.com?utm_medium=email&utm_source=footer>.

For more options, visit https://groups.google.com/d/optout.

0 Likes

#12

Hi Scott,

    There are still some bits left to hook WAMP-CRA into Crossbar .. I do
    that in the coming days and come back to you.

Ok, great. For now, it seems that even if my javascript client requests
wampcra authentication, if the server side isn't configured with any
authentication, the connection is allowed to be made. This is great for
me at the current time, but is this the behavior you would expect?

Yes, that is expected, because:

- if you don't configure authentication in Crossbar.io it'll automatically "authenticate" the client under role "anonymous"

- it'll authenticate the client under role "anyonymous" (using authentication method "anonymous") _regardless_ what auth methods the client was requesting

Whether that is really a good idea is a different question;)

https://github.com/crossbario/crossbar/issues/112

Please comment there if you like .. I'd be interested on what you think the default/fallback behavior should be.

It's the old "secure by default" (anyone denied without explicit config) vs the "works by default" (anyone allowed conveniently without explicit config) philosophy question.

···

===

Anyway, if you modify your transport configuration for (note the empty "auth" dictionary):

          "transports": [
             {
                "type": "web",
                "endpoint": {
                   "type": "tcp",
                   "port": 8080
                },
                "paths": {
                   "/": {
                      "type": "static",
                      "directory": ".."
                   },
                   "ws": {
                      "type": "websocket",
                      "auth": {
                      }
                   }
                }
             }
          ]

and connect a AutobahnJS client, you get

{reason: "wamp.error.not_authorized", message: "authentication using method 'wampcra' denied by configuration", ..

in the connection close handler.

    I am happy that you already see where Crossbar can bring benefits to
    your applications and systems. The ability for flexible component
    deployment - without changing a single line of app code - is one of
    those.

Yes, it's pretty awesome! I was just fiddling around with my configs,
and I got my application and router workers to run in separate crossbar
nodes, which is so cool.

Oh, yes. You can really build distributed systems without loosing your mind;) And we'll get to yet another dimension as soon as we have router-to-router, to build federations/clusters of routers.

Cheers,
/Tobias

0 Likes

#13

Hi Tobias,

···

On Monday, September 1, 2014 7:30:21 AM UTC-6, Tobias Oberstein wrote:

Hi Scott,

There are still some bits left to hook WAMP-CRA into Crossbar .. I do
that in the coming days and come back to you.

Ok, great. For now, it seems that even if my javascript client requests

wampcra authentication, if the server side isn’t configured with any

authentication, the connection is allowed to be made. This is great for

me at the current time, but is this the behavior you would expect?

Yes, that is expected, because:

  • if you don’t configure authentication in Crossbar.io it’ll
    automatically “authenticate” the client under role “anonymous”

  • it’ll authenticate the client under role “anyonymous” (using
    authentication method “anonymous”) regardless what auth methods the
    client was requesting

Whether that is really a good idea is a different question;)

https://github.com/crossbario/crossbar/issues/112

Please comment there if you like … I’d be interested on what you think
the default/fallback behavior should be.

It’s the old “secure by default” (anyone denied without explicit config)
vs the “works by default” (anyone allowed conveniently without explicit
config) philosophy question.

I personally take the view that things should work without extra effort. Adding security should be what requires something extra. But like you said, it’s an age-old debate :slight_smile:

Thanks for your response!

Cheers,

Scott

0 Likes