# Why can't custom properties and methods be accessed from a component that is obtained using SwingUtilities.getAncestorOfClass?

**URL:** <https://forum.inductiveautomation.com/t/why-cant-custom-properties-and-methods-be-accessed-from-a-component-that-is-obtained-using-swingutilities-getancestorofclass/78606>\
**Category:** Ignition\
**Tags:** vision, scripting\
**Created:** [August 31, 2023, 10:07am UTC](https://forum.inductiveautomation.com/t/why-cant-custom-properties-and-methods-be-accessed-from-a-component-that-is-obtained-using-swingutilities-getancestorofclass/78606 "2023-08-31T10:07:05Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![justinedwards.jle](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/justinedwards.jle/32/37854_2.png) [@justinedwards.jle](https://forum.inductiveautomation.com/u/justinedwards.jle)\
**Post date:** [August 31, 2023, 10:07am UTC](https://forum.inductiveautomation.com/t/why-cant-custom-properties-and-methods-be-accessed-from-a-component-that-is-obtained-using-swingutilities-getancestorofclass/78606/1 "2023-08-31T10:07:05Z")

</div>

When I need to get a certain type of parent from a generic component such as a template, and I can't predict how deeply the component will be nested from one instance to the next, I simply obtain the parent with swing utilities because it's simpler and cleaner than a recursive script. However, every now and then, I find myself retrieving a parent component with a custom method or property that I need to call or manipulate, and if I use swing utilities, I find that the custom attributes are lost.

Obviously, this is not a show stopper because this scenario doesn't occur very often, and when it does, I can simply use a recursive function instead, but I'm curious why this is, and if there is a simple work around.

---

<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:** [August 31, 2023, 2:26pm UTC](https://forum.inductiveautomation.com/t/why-cant-custom-properties-and-methods-be-accessed-from-a-component-that-is-obtained-using-swingutilities-getancestorofclass/78606/2 "2023-08-31T14:26:37Z")

</div>

Custom properties are added to the java standard jython conversion by IA's `PyComponentWrapper`. For a complete discussion, read this entire topic:

> [@Transaction groups triggered expression item updating when trigger is false](https://forum.inductiveautomation.com/t/transaction-groups-triggered-expression-item-updating-when-trigger-is-false/17196/14):
>
> Ok, so I’ve been down the rabbit hole and found Ignition’s (undocumented) PyComponentWrapper. I haven’t deciphered it enough to be sure, but it seems to be invoked only for particular situations, based on the string constants in the class file (like “getComponent” and “getComponents”). To play with this, I constructed a conversion adapter like so: public class PyComponentAdapter implements PyObjectAdapter { public PyComponentAdapter() {} @Override public boolean canAdapt(Object jObj) { …

TL/DR: Install my ~~Simulation Aids~~ _Integration Toolkit_ module to magically fix this, everywhere in Ignition. ~~There is _ **no other solution** _ until IA eventually does this first party.~~ _See below._

---

<div class="post-metadata">

**Author:** ![justinedwards.jle](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/justinedwards.jle/32/37854_2.png) [@justinedwards.jle](https://forum.inductiveautomation.com/u/justinedwards.jle)\
**Post date:** [September 1, 2023, 12:20am UTC](https://forum.inductiveautomation.com/t/why-cant-custom-properties-and-methods-be-accessed-from-a-component-that-is-obtained-using-swingutilities-getancestorofclass/78606/3 "2023-09-01T00:20:03Z")

</div>

> [@pturmel](#):
>
> Custom properties are added to the java standard jython conversion by IA's `PyComponentWrapper`.

Thanks for the hint. Wrapping the swing utility call in the PyComponentWrapper returns the object with the custom properties accessible.

Just for completeness and clarity; the recursive approach always works for returning a component with its custom properties.

**Recursive example to get the parent container of a component:**

```auto
from com.inductiveautomation.factorypmi.application.components import BasicContainer
def getParentContainer(component):
	if isinstance(component.parent, BasicContainer):
		return component.parent
	else:
		parentContainer = getParentContainer(component.parent)
		if parentContainer is not None:
			return parentContainer
parentContainer = getParentContainer(event.source)

```

The getAncestorOfClass approach returns the expected component and takes far fewer lines of code, but all custom properties are lost:

**Basic SwingUtilities Example:**

```auto
from com.inductiveautomation.factorypmi.application.components import BasicContainer
from javax.swing import SwingUtilities
parentContainer = SwingUtilities.getAncestorOfClass(BasicContainer, event.source)

```

By simply wrapping the swing utility call in a pyComponentWrapper call, the component is returned with the custom properties just like the recursive approach.

**pyComponentWrapper with SwingUtilities example:**

```auto
from com.inductiveautomation.factorypmi.application.components import BasicContainer
from com.inductiveautomation.factorypmi.application.script import PyComponentWrapper
from javax.swing import SwingUtilities
parentContainer = PyComponentWrapper(SwingUtilities.getAncestorOfClass(BasicContainer, event.source))

```

It's only one more line of code, and it's still cleaner looking than building a recursive function.

---

<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:** [September 1, 2023, 1:13am UTC](https://forum.inductiveautomation.com/t/why-cant-custom-properties-and-methods-be-accessed-from-a-component-that-is-obtained-using-swingutilities-getancestorofclass/78606/4 "2023-09-01T01:13:53Z")

</div>

> [@justinedwards.jle](#):
>
> Wrapping the swing utility call in the PyComponentWrapper returns the object with the custom properties accessible.

Neat. Hadn't thought of that.

Not as neat as never worrying about it again after installing Simulation Aids.
