Tooltip not showing for scripting function for child of abstract parent

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:

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:

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

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

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
    }
}
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:

    @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.

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 /:

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

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,

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

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.

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

That is:

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

Would have a corresponding

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:

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:

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.

1 Like