IllegalStateException: No node currently selected - multiple program node types

I have been struggling with this exception in my own project, and I went to the trouble to create a reproducible test case starting with the Hello World Swing example. I wasn’t sure what was causing the issue, so I made a number of changes to the example. The key change seems to be adding a second program node type in my URCap. Once I did this, I could reliably generate an exception. I then modified my URCap structure to match the pickorplace example, since that has two program nodes. They were in separate packages, so I split mine up that way too. It didn’t help. The exception only happens when you load a saved program. Things are okay with newly inserted nodes.

Below are the steps I followed to reproduce the issue plus the stack trace. I have my modified URCap source code in a tarball, but I don’t see a way to attach it here.

  1. Download latest sdk (1.3.55), install for ur 3.6
  2. Start with HelloWorldSwing example. Add some checkboxes and a second program node type (project attached, drop in SDK swing examples directory).
  3. Edit pom.xml to install to URSim in Docker (change ip-address, update activator bundle)
  4. Running URSim 3.6.1.30595 (Jun 19 2018)
  5. build and install using mvn install –P ursimvm
  6. Load Empty Program
  7. Add a Hello Exception node and a Hello Exception 2 node.
  8. Note that checkboxes can be clicked.
  9. Save program and exit URSIm
  10. Restart URSim and Load program again.
  11. Note that clicking checkboxes in Hello Exception Node 2 causes exception shown below.

Activator says Hello World!
Jul 29, 2018 6:17:16 PM com.steadystate.css.parser.CSSOMParser
WARNING: java.lang.ClassNotFoundException: com.steadystate.css.parser.SACParserCSS21 not found by org.w3c.css.sac [70]
Jul 29, 2018 6:17:16 PM com.steadystate.css.parser.CSSOMParser
WARNING: using the default ‘SACParserCSS21’ instead
ERROR [RobotState - PostMan] 18:17:28 29/07/18 RobotState$PostMan.work(line:263): RobotState messages are queued up: 4
Contrib says Something
Contrib says Something
ERROR [AWT-EventQueue-0] 18:17:59 29/07/18: Caught an unhandled exception
java.lang.IllegalStateException: No node currently selected.
at com.ur.urcap.contribution.program.SwingProgramNodeViewProviderImpl$1.get(SwingProgramNodeViewProviderImpl.java:100)
at com.ur.urcap.examples.helloworldswing.node2.HelloWorldNode2View$2.actionPerformed(HelloWorldNode2View.java:61)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2022)
at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2348)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
at javax.swing.JToggleButton$ToggleButtonModel.setPressed(JToggleButton.java:308)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:252)
at java.awt.Component.processMouseEvent(Component.java:6533)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3324)
at java.awt.Component.processEvent(Component.java:6298)
at java.awt.Container.processEvent(Container.java:2238)
at java.awt.Component.dispatchEventImpl(Component.java:4889)
at java.awt.Container.dispatchEventImpl(Container.java:2296)
at java.awt.Component.dispatchEvent(Component.java:4711)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4897)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4534)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4475)
at java.awt.Container.dispatchEventImpl(Container.java:2282)
at java.awt.Window.dispatchEventImpl(Window.java:2746)

I think I’ve finally fixed this issue. It seems like the problem has to do with the lifetime and multiplicity of the Contribution class relative to the View class. There is one View class instance and buildUI is only called once. There are multiple Contribution class instances (one for every node in the program of that type). Because of this, any caching of the Contribution class inside the View class is dangerous. In particular, the “provider” variable passed during buildUI cannot be used later. So when you create actionListener methods for GUI controls, you can’t code anything like provider.get().someFunction(). By the time the event handler is called, provider may no longer be valid. To get around this, I made all event handlers call methods in the View class itself. These event handlers don’t call provider, they call methods on a reference to the Contribution class itself. This reference is kept up to date by having the Contribution always pass a reference to itself to the view when openView is called, and clear this reference when closeView is called. Does this make sense? Have others used this pattern?

You are correct in the observation, that there for program nodes exist only one View, while there may be multiple Contributions.
The “provider” you get during buildUI is only valid, when a node is selected and the View is opened.
But the View should also only interact with the Contribution, when the user alters the View (ie. interacts with an input).

This article may elaborate a bit;
https://plus.universal-robots.com/getting-started/principle-of-urcaps-integration-in-polyscope/