# ClientTagProvider.subscribeAsync

**URL:** <https://forum.inductiveautomation.com/t/clienttagprovider-subscribeasync/84335>\
**Category:** Module Development\
**Created:** [January 16, 2024, 5:30pm UTC](https://forum.inductiveautomation.com/t/clienttagprovider-subscribeasync/84335 "2024-01-16T17:30:58Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![Mathias\_Melling](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/mathias_melling/32/67682_2.png) [@Mathias\_Melling](https://forum.inductiveautomation.com/u/Mathias_Melling)\
**Post date:** [January 16, 2024, 5:30pm UTC](https://forum.inductiveautomation.com/t/clienttagprovider-subscribeasync/84335/1 "2024-01-16T17:30:58Z")

</div>

com.inductiveautomation.ignition.client.tags.model.ClientTagProvider  
`subscribeAsync(List<TagPath>, List<TagChangeListener>)`

How do I use this method? My class is extending `AbstracVisionShape`, so I'm using the context that is provided by that extension to get to  
`context.getTagManager().getDefaultProvider().subscribeAsync`

I understand how to build a list of Tag Paths to feed into the subscribe method, but what do I do about the list of `TagChangeListeners`?

---

<div class="post-metadata">

**Author:** ![lrose](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/lrose/32/62724_2.png) [@lrose](https://forum.inductiveautomation.com/u/lrose)\
**Post date:** [January 16, 2024, 5:34pm UTC](https://forum.inductiveautomation.com/t/clienttagprovider-subscribeasync/84335/2 "2024-01-16T17:34:21Z")

</div>

Well, if you're subscribing to tag updates, that would imply that you are going to need a listener. So you would have to build an event listener which implements TagChangeListener and then provide that to the method.

What are you really trying to achieve though? Do you need to listen for tag changes at all?

---

<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 16, 2024, 5:35pm UTC](https://forum.inductiveautomation.com/t/clienttagprovider-subscribeasync/84335/3 "2024-01-16T17:35:02Z")

</div>

`TagChangeListener` is just a functional interface acting as a callback. You provide a list of tag paths and a matching length list of "do this when the tag changes" functions - which could technically all be the same, if you want, since `TagChangeEvent` includes the path that actually invoked the change.

---

<div class="post-metadata">

**Author:** ![Mathias\_Melling](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/mathias_melling/32/67682_2.png) [@Mathias\_Melling](https://forum.inductiveautomation.com/u/Mathias_Melling)\
**Post date:** [January 16, 2024, 5:38pm UTC](https://forum.inductiveautomation.com/t/clienttagprovider-subscribeasync/84335/4 "2024-01-16T17:38:49Z")

</div>

Yes, I need to listen for tag changes on a dynamic list of tags.  
Can I implement `TagChangeListener` on the class I'm working on already?

---

<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 16, 2024, 5:41pm UTC](https://forum.inductiveautomation.com/t/clienttagprovider-subscribeasync/84335/5 "2024-01-16T17:41:08Z")

</div>

Sure - why not? Just pass it as `Collections.nCopies(tagpaths.size(), this)` or whatever else is appropriate.

---

<div class="post-metadata">

**Author:** ![Mathias\_Melling](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/mathias_melling/32/67682_2.png) [@Mathias\_Melling](https://forum.inductiveautomation.com/u/Mathias_Melling)\
**Post date:** [January 16, 2024, 5:48pm UTC](https://forum.inductiveautomation.com/t/clienttagprovider-subscribeasync/84335/6 "2024-01-16T17:48:51Z")

</div>

Something like this?

```auto
List<TagPath> tagPaths = new ArrayList<>();
        for (Object s: sources.getColumnAsList(0)) {
            int endIndex = s.toString().length();
            tagPaths.add(TagPathParser.parse(
                s.toString().substring(0,endIndex) + "_Color"));
        }

List<TagChangeListener> tagListeners = Collections.nCopies(tagPaths.size(), this);

context.getTagManager().getDefaultProvider().subscribeAsync(
                tagPaths, 
                tagListeners);

```

---

<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 16, 2024, 5:53pm UTC](https://forum.inductiveautomation.com/t/clienttagprovider-subscribeasync/84335/7 "2024-01-16T17:53:39Z")

</div>

Sure, that should work. That code to generate the tag paths seems more complex than necessary, but it should work.

---

<div class="post-metadata">

**Author:** ![Mathias\_Melling](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/mathias_melling/32/67682_2.png) [@Mathias\_Melling](https://forum.inductiveautomation.com/u/Mathias_Melling)\
**Post date:** [January 16, 2024, 5:57pm UTC](https://forum.inductiveautomation.com/t/clienttagprovider-subscribeasync/84335/8 "2024-01-16T17:57:11Z")

</div>

Any recommendation to make that less complex would be appreciated as well 😁  
I just started learing Java 3 months ago, so I'm not all that efficient in it.

---

<div class="post-metadata">

**Author:** ![Mathias\_Melling](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/mathias_melling/32/67682_2.png) [@Mathias\_Melling](https://forum.inductiveautomation.com/u/Mathias_Melling)\
**Post date:** [January 16, 2024, 6:03pm UTC](https://forum.inductiveautomation.com/t/clienttagprovider-subscribeasync/84335/9 "2024-01-16T18:03:04Z")

</div>

There, that's less complex now!

```auto
List<TagPath> tagsPaths = new ArrayList<>();
for (Object s: sources.getColumnAsList(0)) {
   tagsPaths.add(TagPathParser.parse(s.toString() + "_Color"));

```

---

<div class="post-metadata">

**Author:** ![Mathias\_Melling](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/mathias_melling/32/67682_2.png) [@Mathias\_Melling](https://forum.inductiveautomation.com/u/Mathias_Melling)\
**Post date:** [January 16, 2024, 7:01pm UTC](https://forum.inductiveautomation.com/t/clienttagprovider-subscribeasync/84335/10 "2024-01-16T19:01:06Z")

</div>

I have the above mentioned code under a property setter called `setSources()`.  
When I open a window in Ignititon with this component on it, it complains that `context` is null. So `setSources()` runs before the component is handed a context.  
How can I prevent any property setters from running before `startupComponent` is complete?

---

<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 16, 2024, 7:30pm UTC](https://forum.inductiveautomation.com/t/clienttagprovider-subscribeasync/84335/11 "2024-01-16T19:30:06Z")

</div>

You cannot stop them. But you can cache the values and apply them after your own component startup.

---

<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 16, 2024, 7:54pm UTC](https://forum.inductiveautomation.com/t/clienttagprovider-subscribeasync/84335/12 "2024-01-16T19:54:08Z")

</div>

One option, opinions and your mileage may vary, is the stream API:

```java
List<TagPath> tagsPaths = sources.getColumnAsList(0).stream()
            .map(s -> TagPathParser.parseSafe(s.toString() + "_Color"))
            .collect(Collectors.toList()); // or .toList(), if you're compiling against Ignition 8.1.33 or later

```

Note that Java streams are _not_ a zero-cost abstraction, and the imperative solution with a for loop will pretty much always win in a direct performance comparison. But the stream API has (debatable) advantages in emphasizing "correctness", such as by strongly discouraging side effects and pushing towards "pure" functional operations.

---

<div class="post-metadata">

**Author:** ![Mathias\_Melling](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/mathias_melling/32/67682_2.png) [@Mathias\_Melling](https://forum.inductiveautomation.com/u/Mathias_Melling)\
**Post date:** [January 16, 2024, 9:45pm UTC](https://forum.inductiveautomation.com/t/clienttagprovider-subscribeasync/84335/13 "2024-01-16T21:45:25Z")

</div>

How would I go about that?
