# Custom Vision Component Event Handler Information

**URL:** <https://forum.inductiveautomation.com/t/custom-vision-component-event-handler-information/68327>\
**Category:** Module Development\
**Tags:** vision\
**Created:** [January 6, 2023, 8:42pm UTC](https://forum.inductiveautomation.com/t/custom-vision-component-event-handler-information/68327 "2023-01-06T20:42:38Z")\
**Posts on this page:** 17\
**Page:** 1

<div class="post-metadata">

**Author:** ![eric.hollering](https://avatars.discourse-cdn.com/v4/letter/e/ad7895/32.png) [@eric.hollering](https://forum.inductiveautomation.com/u/eric.hollering)\
**Post date:** [January 6, 2023, 8:42pm UTC](https://forum.inductiveautomation.com/t/custom-vision-component-event-handler-information/68327/1 "2023-01-06T20:42:38Z")

</div>

I'm trying to create a very simple Vision component with some event scripting.

I've got the component working but am trying to figure out how to populate the Event Description and Event Object Properties at the bottom of the scripting window.

![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/e/9/e9b4dc55bf149360ec4a554832215dccdf1f33c2.png)

I'm using an ActionAdapter to try to help me out by setting up a default script and populating the metadata, and I think what I'm probably missing is the [ActionAdapter.setBuilderInfo()](https://files.inductiveautomation.com/sdk/javadoc/ignition81/8.1.23/com/inductiveautomation/factorypmi/application/binding/action/ActionAdapter.html#setBuilderInfo(java.util.Map))) method, but since it just takes a Map\<String, Object\> I'm really not sure what I need to supply to it to make it work as expected, or if this is even the right approach.

Anyone have any insight to offer to help me get this populated with information that would help my end users know what they're getting with these events?

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [January 6, 2023, 9:34pm UTC](https://forum.inductiveautomation.com/t/custom-vision-component-event-handler-information/68327/2 "2023-01-06T21:34:16Z")

</div>

Here is a snippet from my Batik SVG component's BeanInfo that shows what you should be doing:

```auto
	protected void initEventSets() throws IntrospectionException {
		super.initEventSets();
		addEventSet(ScalableVectorCanvas.class, "SVGDocumentLoader",
				SVGDocumentLoaderListener.class, SVGDocumentLoaderEvent.class,
				new String[] { "documentLoadingStarted", "documentLoadingCompleted",
						"documentLoadingCancelled", "documentLoadingFailed" });
		addEventSet(ScalableVectorCanvas.class, "GVTTreeBuilder",
				GVTTreeBuilderListener.class, GVTTreeBuilderEvent.class,
				new String[] { "gvtBuildStarted", "gvtBuildCompleted",
						"gvtBuildCancelled", "gvtBuildFailed" });
		addEventSet(ScalableVectorCanvas.class, "linkActivation",
				LinkActivationListener.class, "linkActivated");
		addEventSet(ScalableVectorCanvas.class, "SVGLoadEventDispatcher",
				SVGLoadEventDispatcherListener.class, SVGLoadEventDispatcherEvent.class,
				new String[] { "svgLoadEventDispatchStarted", "svgLoadEventDispatchCompleted",
						"svgLoadEventDispatchCancelled", "svgLoadEventDispatchFailed" });
		addEventSet(ScalableVectorCanvas.class, "updateManager",
				UpdateManagerListener.class, UpdateManagerEvent.class,
				new String[] { "managerStarted", "managerSuspended",
						"managerResumed", "managerStopped",
						"updateStarted", "updateCompleted", "updateFailed" });
	}

```

Start with the [javadoc for addEventSet()](https://files.inductiveautomation.com/sdk/javadoc/ignition81/8.1.1/com/inductiveautomation/vision/api/designer/beans/DefaultBeanInfo.html#addEventSet(java.lang.Class,java.lang.String,java.lang.Class,java.lang.Class,java.lang.String%5B%5D,java.lang.String,java.lang.String,java.lang.String)).

---

<div class="post-metadata">

**Author:** ![eric.hollering](https://avatars.discourse-cdn.com/v4/letter/e/ad7895/32.png) [@eric.hollering](https://forum.inductiveautomation.com/u/eric.hollering)\
**Post date:** [January 6, 2023, 9:39pm UTC](https://forum.inductiveautomation.com/t/custom-vision-component-event-handler-information/68327/3 "2023-01-06T21:39:29Z")

</div>

Mine is pretty similar, or at least I can't see the difference, but how does it get the event description and event object parameters? Mine are still empty as in the screenshot.

```auto
    @Override
    protected void initEventSets() throws IntrospectionException {
        super.initEventSets();
        this.addEventSet(
                LiftEventComponent.class,
                "eventReceived",
                LiftEventListener.class,
                LiftEventObject.class,
                new String[]{"onEventReceived"});

```

Is it using the values from a property bundle perhaps? I don't have one of those wired up for these classes yet. Maybe that's the issue?

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [January 6, 2023, 10:06pm UTC](https://forum.inductiveautomation.com/t/custom-vision-component-event-handler-information/68327/4 "2023-01-06T22:06:29Z")

</div>

Good question. Not sure. It definitely uses introspection somehow.

---

<div class="post-metadata">

**Author:** ![eric.hollering](https://avatars.discourse-cdn.com/v4/letter/e/ad7895/32.png) [@eric.hollering](https://forum.inductiveautomation.com/u/eric.hollering)\
**Post date:** [January 6, 2023, 10:38pm UTC](https://forum.inductiveautomation.com/t/custom-vision-component-event-handler-information/68327/5 "2023-01-06T22:38:02Z")

</div>

So one key difference is that I diverted from the standard convention for the add/remove/get listener methods. After reviewing the docs I saw an overload that takes those method names, so I've changed it to this, but still no dice.

```auto
    @Override
    protected void initEventSets() throws IntrospectionException {
        super.initEventSets();
        this.addEventSet(
                LiftEventComponent.class,
                "eventReceived",
                LiftEventListener.class,
                LiftEventObject.class,
                new String[]{"onEventReceived"},
                "addEventReceivedListener",
                "removeEventReceivedListener",
                "getEventReceivedListeners");
    }

```

---

<div class="post-metadata">

**Author:** ![eric.hollering](https://avatars.discourse-cdn.com/v4/letter/e/ad7895/32.png) [@eric.hollering](https://forum.inductiveautomation.com/u/eric.hollering)\
**Post date:** [January 6, 2023, 11:16pm UTC](https://forum.inductiveautomation.com/t/custom-vision-component-event-handler-information/68327/6 "2023-01-06T23:16:23Z")

</div>

Adding a properties file didn't seem to help, assuming I did it correctly.

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [January 9, 2023, 8:24pm UTC](https://forum.inductiveautomation.com/t/custom-vision-component-event-handler-information/68327/7 "2023-01-09T20:24:35Z")

</div>

It looks like you could, in theory, populate a custom event description with a well formatted bundle key:

```java
String eventSetName = node.getParent().getEventSet().getName();
String descString = BundleUtil.get().getString(
    "events." + eventSetName + "." + node.getMethodDescriptor().getName(),
    "<i>(Documentation Missing)");
eventDesc.setText("<html>" + descString);

```

So something like `events.eventReceived.onEventReceived=Your event description`.  
Again, in theory.

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [January 9, 2023, 9:52pm UTC](https://forum.inductiveautomation.com/t/custom-vision-component-event-handler-information/68327/8 "2023-01-09T21:52:23Z")

</div>

Is it possible to add another "events" bundle to merge with IA's bundle?

---

<div class="post-metadata">

**Author:** ![eric.hollering](https://avatars.discourse-cdn.com/v4/letter/e/ad7895/32.png) [@eric.hollering](https://forum.inductiveautomation.com/u/eric.hollering)\
**Post date:** [January 9, 2023, 10:10pm UTC](https://forum.inductiveautomation.com/t/custom-vision-component-event-handler-information/68327/9 "2023-01-09T22:10:43Z")

</div>

Would I add that to the properties file of the BeanInfo class or the component class?

Or am I even more confused that I think I am? 😁

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [January 9, 2023, 10:45pm UTC](https://forum.inductiveautomation.com/t/custom-vision-component-event-handler-information/68327/10 "2023-01-09T22:45:36Z")

</div>

I **think** you could do something like:

1. Add an "xyz.properties" file to the _root_ of your module's resources.
2. Add keys following the `events.eventReceived.onEventReceived` format above.
3. Register your bundle in the "common" scope in your designer hook: `BundleUtil.get().addCommonBundle("xyz")`

---

<div class="post-metadata">

**Author:** ![eric.hollering](https://avatars.discourse-cdn.com/v4/letter/e/ad7895/32.png) [@eric.hollering](https://forum.inductiveautomation.com/u/eric.hollering)\
**Post date:** [January 9, 2023, 11:08pm UTC](https://forum.inductiveautomation.com/t/custom-vision-component-event-handler-information/68327/11 "2023-01-09T23:08:29Z")

</div>

That worked! Thanks so much!

---

<div class="post-metadata">

**Author:** ![eric.hollering](https://avatars.discourse-cdn.com/v4/letter/e/ad7895/32.png) [@eric.hollering](https://forum.inductiveautomation.com/u/eric.hollering)\
**Post date:** [January 9, 2023, 11:20pm UTC](https://forum.inductiveautomation.com/t/custom-vision-component-event-handler-information/68327/12 "2023-01-09T23:20:47Z")

</div>

So that worked for the event description, and I thought I could easily figure out the parameter section from there, but I've tried a couple things and it's not obvious to me.

Do you know what magic key might fill out the Event Object Properties?

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [January 10, 2023, 12:05am UTC](https://forum.inductiveautomation.com/t/custom-vision-component-event-handler-information/68327/13 "2023-01-10T00:05:07Z")

</div>

😬  
There's no dynamic way to add new event object properties, _in a supported manner_.

If you hold your nose...  
`com.inductiveautomation.factorypmi.designer.eventhandling.ActionConfigPanel#EVENT_OBJECTS` is a package-private hashmap `String` to `String[]`.  
If you got a reference to that field, you could add your own key/value (e.g. `eventReceived` as the key, your list of possible parameters for all of these events as the value). Then add keys in the format  
`eventobj.eventReceived.property=My event object parameter`, and things, again, _might_ work. Your different events will all be assumed to receive the same parameters.

---

<div class="post-metadata">

**Author:** ![eric.hollering](https://avatars.discourse-cdn.com/v4/letter/e/ad7895/32.png) [@eric.hollering](https://forum.inductiveautomation.com/u/eric.hollering)\
**Post date:** [January 10, 2023, 4:57pm UTC](https://forum.inductiveautomation.com/t/custom-vision-component-event-handler-information/68327/15 "2023-01-10T16:57:58Z")

</div>

Well, obviously it would be nice to have a supported way to do this to create an ideal user experience for our custom component.

However, the "hold your nose" approach does appear to work.

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [January 10, 2023, 5:12pm UTC](https://forum.inductiveautomation.com/t/custom-vision-component-event-handler-information/68327/16 "2023-01-10T17:12:00Z")

</div>

Agreed. I could put it on the books, but honestly I don't think it's going to buy you much compared to the "hold your nose" approach. I would consider your approach "safe" for the foreseeable future; we're pretty unlikely to refactor something this fundamental to Vision at this stage of the game; if we ever do, we'll surely replace it with an actual API.

---

<div class="post-metadata">

**Author:** ![eric.hollering](https://avatars.discourse-cdn.com/v4/letter/e/ad7895/32.png) [@eric.hollering](https://forum.inductiveautomation.com/u/eric.hollering)\
**Post date:** [January 10, 2023, 7:15pm UTC](https://forum.inductiveautomation.com/t/custom-vision-component-event-handler-information/68327/17 "2023-01-10T19:15:36Z")

</div>

Totally understand. Thanks again.

For those who may be interested in this topic, here's the relevant code to do this unsupported thing that you should only do as a last resort.

This goes in the DesignerHook class; I put it in the _onStartup()_ method. This implies that you've declared a dependency on the Vision module..

```auto
 var visionSdk = (VisionDesignerInterface) context.getModule(VisionDesignerInterface.VISION_MODULE_ID);

  // If the Vision module is installed, add our component to the palette
  if (visionSdk != null) {
      var palette = visionSdk.getPalette();

      var group = palette.addGroup("Your Custom Components");
      group.addPaletteItem(new JavaBeanPaletteItem(YourComponent.class));

      
      try {
          var actionConfigPanelClass = Class.forName("com.inductiveautomation.factorypmi.designer.eventhandling.ActionConfigPanel");
          var eventObjectsField = actionConfigPanelClass.getDeclaredField("EVENT_OBJECTS");
          boolean accessibility = eventObjectsField.canAccess(null);
          eventObjectsField.setAccessible(true);

          var eventObjects = (Map<String, String[]>) eventObjectsField.get(actionConfigPanelClass);
          if (!eventObjects.containsKey("eventReceived")) {
              eventObjects.put("eventReceived", new String[]{"source", "eventName", "eventData"});
          }

          eventObjectsField.setAccessible(accessibility);
      } catch (Exception e) {
          e.printStackTrace();
      }
  }

```

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [December 13, 2024, 8:12pm UTC](https://forum.inductiveautomation.com/t/custom-vision-component-event-handler-information/68327/19 "2024-12-13T20:12:28Z")

</div>

No, I never messed with the default events that IA sets up.
