# Tooltip not showing for scripting function for child of abstract parent

**URL:** <https://forum.inductiveautomation.com/t/tooltip-not-showing-for-scripting-function-for-child-of-abstract-parent/69716>\
**Category:** Module Development\
**Tags:** scripting\
**Created:** [February 10, 2023, 7:59pm UTC](https://forum.inductiveautomation.com/t/tooltip-not-showing-for-scripting-function-for-child-of-abstract-parent/69716 "2023-02-10T19:59:51Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Tyler\_Dolan](https://avatars.discourse-cdn.com/v4/letter/t/b5ac83/32.png) [@Tyler\_Dolan](https://forum.inductiveautomation.com/u/Tyler_Dolan)\
**Post date:** [February 10, 2023, 7:59pm UTC](https://forum.inductiveautomation.com/t/tooltip-not-showing-for-scripting-function-for-child-of-abstract-parent/69716/1 "2023-02-10T19:59:51Z")

</div>

Sorry if the title doesn't make sense. To elaborate, I have tried replicating the scripting functions example to create documentation for my scripting functions through annotations, but it's not working as I'd expect it to. The tooltip for system.kpi.create just says "No return value" and the description is null.

In my common scripting folder I have:

```auto
public abstract class AbstractScriptApi<T extends Model> implements ScriptApi<T> {

    public AbstractScriptApi() {
        BundleUtil.get().addBundle("AbstractScriptApi", AbstractScriptApi.class.getClassLoader(), "AbstractScriptApi");
    }

    @Override
    @ScriptFunction(docBundlePrefix = "AbstractScriptApi")
    public T create() {
        return createImpl();
    }

    protected abstract T createImpl();
}

```

and AbstractScriptApi.properties in the respective resources folder:

```auto
create.desc = test description.
create.returns = test return.

```

Then in client, AbstractClientScriptApi extends AbstractScriptApi, and KPIClientScriptApi extends AbstractClientScriptApi :

```auto
public abstract class AbstractClientScriptApi<T extends Model> extends AbstractScriptApi<T> implements ScriptApi<T> {

    private final Class<? extends ScriptApi<T>> type;
    protected final RpcProxy rpc;

    public AbstractClientScriptApi(Class<? extends ScriptApi<T>> type) {
        this.type = type;
        //create rpc

        BundleUtil.get().addBundle("AbstractClientScriptApi", AbstractClientScriptApi.class.getClassLoader(),"AbstractClientScriptApi");
    }

    @ScriptFunction(docBundlePrefix = "AbstractClientScriptApi")
    public T createImpl() {
        //rpc call to gateway
    }
}

```

```auto
public class KPIClientScriptApi extends AbstractClientScriptApi<KPI> implements IKPIScriptApi{

    public KPIClientScriptApi() {
        super(IKPIScriptApi.class);
        BundleUtil.get().addBundle("KPIClientScriptApi", getClass(),"KPIClientScriptApi");
    }
}

```

I have similar structure for the respective gateway classes. In the client and designer hooks I have:

```auto
    @Override
    public void initializeScriptManager(ScriptManager manager) {
        super.initializeScriptManager(manager); 
        manager.addScriptModule("system.kpi", injector.getInstance(KPIClientScriptApi.class), new PropertiesFileDocProvider());      
    }

```

And I have a similar initialization in the gateway hook for the respective gateway KPI class.

I will eventually have many classes that extend AbstractClientScriptApi which will have many more methods, so it would be nice to only have to put documentation in one place.

I've been on this for a while, so any help would be appreciated.

---

<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:** [February 10, 2023, 11:37pm UTC](https://forum.inductiveautomation.com/t/tooltip-not-showing-for-scripting-function-for-child-of-abstract-parent/69716/2 "2023-02-10T23:37:19Z")

</div>

I don't see anything obviously wrong with your implementation, so I'll start with the most obvious BundleUtil related troubleshooting step... have you restarted the gateway since installing your module?

The only thing I see that might be an issue is the path you're loading your bundle at.  
Notice how the example module uses the fully qualified class name, but with `.` replace with `/`:

> <https://github.com/inductiveautomation/ignition-sdk-examples/blob/4c4552578fec89082a207cca68f36d27e920c7d1/scripting-function/scripting-function-common/src/main/java/com/inductiveautomation/ignition/examples/scripting/AbstractScriptModule.java#L10-L14>

---

<div class="post-metadata">

**Author:** ![Tyler\_Dolan](https://avatars.discourse-cdn.com/v4/letter/t/b5ac83/32.png) [@Tyler\_Dolan](https://forum.inductiveautomation.com/u/Tyler_Dolan)\
**Post date:** [February 10, 2023, 11:40pm UTC](https://forum.inductiveautomation.com/t/tooltip-not-showing-for-scripting-function-for-child-of-abstract-parent/69716/3 "2023-02-10T23:40:54Z")

</div>

Yes I did restart the gateway, and I tried with the fully qualified path name. Unfortunately it didn't help

---

<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:** [February 10, 2023, 11:51pm UTC](https://forum.inductiveautomation.com/t/tooltip-not-showing-for-scripting-function-for-child-of-abstract-parent/69716/4 "2023-02-10T23:51:32Z")

</div>

You could interrogate BundleUtil at runtime, via scripting, to see where it's loaded your bundles at?  
The PropertiesFileDocProvider is pretty simple, it's ultimately doing simple string concatenation with the `docBundlePrefix` to create a bundle key, e.g.:  
`BundleUtil.get().getString(String.format("%s.%s.returns", getBundlePrefix(m), m.getName())` where `m` is the `java.lang.Method`.

As an aside,

> [@Tyler\_Dolan](#):
>
> ```auto
> @ScriptFunction(docBundlePrefix = "AbstractClientScriptApi")
> public T createImpl() {
> 
> ```

You probably want to leave the visibility `protected`, otherwise users will be able to call both `create()` and `createImpl()` on `system.kpi`.

---

<div class="post-metadata">

**Author:** ![aaronrai24](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/aaronrai24/32/87248_2.png) [@aaronrai24](https://forum.inductiveautomation.com/u/aaronrai24)\
**Post date:** [October 9, 2024, 6:25am UTC](https://forum.inductiveautomation.com/t/tooltip-not-showing-for-scripting-function-for-child-of-abstract-parent/69716/5 "2024-10-09T06:25:47Z")

</div>

> [@paul-griffith](#):
>
> You could interrogate BundleUtil at runtime

Any suggestions on how to go about this, i'm running into the same issue and unsure where I should be placing the `.properties` files in the first place, so i'd be curious to see where they get loaded in the current implementation.

---

<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:** [October 9, 2024, 3:23pm UTC](https://forum.inductiveautomation.com/t/tooltip-not-showing-for-scripting-function-for-child-of-abstract-parent/69716/6 "2024-10-09T15:23:25Z")

</div>

The _convention_ is to put them in the same directory path as your script module code, but in the resources directory.

That is:

```python
src/main/java/path/to/your/package/SomeScriptModule.java

```

Would have a corresponding

```python
src/main/resources/path/to/your/package/SomeScriptModule.properties

```

And then that bundle gets registered using the snippet linked above in a static block in the class:

```java
BundleUtil.get().addBundle(
    SomeScriptModule.class.getSimpleName(),
    SomeScriptModule.class.getClassLoader(),
    SomeScriptModule.class.getName().replace('.', '/')
);

```

If you're using IntelliJ, make sure you're using **actual folders** in the resources directory. IntelliJ's tree UI collapses those entries during navigation to _look_ like packages, just like Java files, and as far as I know there's no way _in IntelliJ_ to tell the difference between:

```python
src/main/resources/path/to/your/package/SomeScriptModule.properties
src/main/resources/path.to.your.package/SomeScriptModule.properties

```

But only the first one will work using the bundle registration snippet posted above.
