# BundleUtil and Scripting Hints in Designer

**URL:** <https://forum.inductiveautomation.com/t/bundleutil-and-scripting-hints-in-designer/94386>\
**Category:** Module Development\
**Tags:** ignition81, scripting\
**Created:** [August 8, 2024, 10:44pm UTC](https://forum.inductiveautomation.com/t/bundleutil-and-scripting-hints-in-designer/94386 "2024-08-08T22:44:10Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![cody.tamaki](https://avatars.discourse-cdn.com/v4/letter/c/b487fb/32.png) [@cody.tamaki](https://forum.inductiveautomation.com/u/cody.tamaki)\
**Post date:** [August 8, 2024, 10:44pm UTC](https://forum.inductiveautomation.com/t/bundleutil-and-scripting-hints-in-designer/94386/1 "2024-08-08T22:44:10Z")

</div>

I'm adding some scripting hints to my designer, and trying to put the script methods in an interface rather than an abstract class (I will only have a gateway representation of this class and am using a Proxy/Invocation handler on the designer side).

I'm using the debugger and see my .properties file loaded into the BundleUtil, but I can't seem to get scripting hints to work?

I have 2 questions really:

1. I'm initializing these bundles in a for loop inside of the initializeScriptManager method in my designer hook. Is that ok or does that maybe need to happen in setup or startup?
2. What's the exact key that scripting hints will be looking for? I'm finding my {docBundlePrefix}.{methodName}.param.{scriptArg} keys, but wanted to make sure I have the format correct on that...

---

<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:** [August 9, 2024, 12:00am UTC](https://forum.inductiveautomation.com/t/bundleutil-and-scripting-hints-in-designer/94386/2 "2024-08-09T00:00:04Z")

</div>

> [@cody.tamaki](#):
>
> - Is that ok or does that maybe need to happen in setup or startup?

Generally, our scripting function implementations register with bundle util in a static block inside them, which would imply deferral until they're actually constructed, so this should be fine; see `AbstractScriptModule` in our public SDK:

> <https://github.com/inductiveautomation/ignition-sdk-examples/blob/276f89239073e2108253716bce7f4ff70d20698d/scripting-function/scripting-function-common/src/main/java/com/inductiveautomation/ignition/examples/scripting/AbstractScriptModule.java#L9>

> [@cody.tamaki](#):
>
> What's the exact key that scripting hints will be looking for?

_Exact_ format depends slightly on if your method is accepting keyword arguments (a `PyObject[], String[]` signature) or regular Java arguments, but that looks correct to me.

Something like the below, where `docBundlePrefix` is _implicit_ (not actually part of your properties file), ex:

> <https://github.com/inductiveautomation/ignition-sdk-examples/blob/276f89239073e2108253716bce7f4ff70d20698d/scripting-function/scripting-function-common/src/main/resources/com/inductiveautomation/ignition/examples/scripting/AbstractScriptModule.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:** [August 9, 2024, 12:10am UTC](https://forum.inductiveautomation.com/t/bundleutil-and-scripting-hints-in-designer/94386/4 "2024-08-09T00:10:44Z")

</div>

While I'm here, I guess I'll also advertise that this system gets a lot more depth in 8.3, and a proper documentation pass:

> **[PropertiesFileDocProvider](https://files.inductiveautomation.com/sdk/javadoc/earlyaccess/ignition83/8.3.0-SNAPSHOT/com/inductiveautomation/ignition/common/script/hints/PropertiesFileDocProvider.html)**
>
> declaration: package: com.inductiveautomation.ignition.common.script.hints, class: PropertiesFileDocProvider

This'll be fully backwards compatible (in that old property keys will continue to work) but with a ton of progressive enhancement available.

---

<div class="post-metadata">

**Author:** ![cody.tamaki](https://avatars.discourse-cdn.com/v4/letter/c/b487fb/32.png) [@cody.tamaki](https://forum.inductiveautomation.com/u/cody.tamaki)\
**Post date:** [August 9, 2024, 3:36pm UTC](https://forum.inductiveautomation.com/t/bundleutil-and-scripting-hints-in-designer/94386/5 "2024-08-09T15:36:07Z")

</div>

Right, so I found my issue and it's basically because I'm trying to do something "special" with Java's Proxy/Invocation Handler API so that I force everything from a designer to be an RPC call to the gateway and only implement the methods there (I only plan on supporting Perspective, so these scripting methods will be purely in designer to play with/debug in the script console).

I ended up extending the PropertiesFileDocProvider to return methods directly from the interface class (which have the @ScriptFunction annotation) instead of using the Proxied instance.

Thanks for your help Paul!

---

<div class="post-metadata">

**Author:** ![Kevin.Herron](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kevin.herron/32/7259_2.png) [@Kevin.Herron](https://forum.inductiveautomation.com/u/Kevin.Herron)\
**Post date:** [August 9, 2024, 3:41pm UTC](https://forum.inductiveautomation.com/t/bundleutil-and-scripting-hints-in-designer/94386/6 "2024-08-09T15:41:16Z")

</div>

> [@cody.tamaki](#):
>
> because I'm trying to do something "special" with Java's Proxy/Invocation Handler API so that I force everything from a designer to be an RPC call to the gateway and only implement the methods there

Why are you reinventing this wheel? It's already what ModuleRPCFactory does, and the scripting example in the SDK repo shows how it's used.

---

<div class="post-metadata">

**Author:** ![cody.tamaki](https://avatars.discourse-cdn.com/v4/letter/c/b487fb/32.png) [@cody.tamaki](https://forum.inductiveautomation.com/u/cody.tamaki)\
**Post date:** [August 9, 2024, 3:52pm UTC](https://forum.inductiveautomation.com/t/bundleutil-and-scripting-hints-in-designer/94386/7 "2024-08-09T15:52:37Z")

</div>

At first it was to proxy 20 different script classes through the single RPC interface. I can have an invocation handler on the designer side that wraps/sends the info as an RPC request and then my RPC handler on the gateway can route that request through to the implementation and return the result.

Also, it's saving me from defining any client side classes. I have interfaces in my common scope, a proxy in the designer scope and all implementation is done in the gateway scope (because that's where all my services/business logic reside anyway). So I don't have any kind of client/designer implementation of the classes at all.

I know the multiple RPC handlers will be resolved in 8.3, but am I misunderstanding something and making it way too complicated?

---

<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 9, 2024, 3:54pm UTC](https://forum.inductiveautomation.com/t/bundleutil-and-scripting-hints-in-designer/94386/8 "2024-08-09T15:54:58Z")

</div>

Consider not doing this at all. Particularly if you can use my [@runInGateway](https://www.automation-pros.com/toolkit/doc/utility.html#runingateway) decorator. You don't want a single script in the designer to call your API in a loop or something like that, yielding many round trips.

---

<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:** [August 9, 2024, 4:08pm UTC](https://forum.inductiveautomation.com/t/bundleutil-and-scripting-hints-in-designer/94386/9 "2024-08-09T16:08:54Z")

</div>

For separation of concerns, I'd strongly recommend \_de\_coupling the scripting interface from the RPC interface. I literally just drew up this diagram yesterday:

 ![image (1)](https://us1.discourse-cdn.com/inductiveautomation/original/3X/2/1/21178f46c783d5c2760b1281b8898006d0598965.png)

Your common scope should define the scripting interface - whatever _public facing_ functions you want to expose via scripting. This is also where you can put your properties files and your argument handling logic.  
Then, once you've unpacked whatever _Jython_ signature into basic _Java_ primitives or module specific objects or whatever, delegate to abstract `impl` methods or a passed in interface or whatever.

It's really tempting to have your scripting interface directly act as your RPC interface, and it'll work...until it doesn't, and untangling the two things becomes something you have to spend a lot of effort doing down the road. Ask me how I know 😄

If you use something like the ModuleRPCFactory Kevin mentioned above and this decoupling I advise (most crucially, being _very_ aware of what types you're sending over the RPC bridge), your migration to 8.3 will be _very_ smooth.
