A mystery in extension functions

I am having trouble getting the default presentation of an extension function within the “scripting” dialog correct. To illustrate the problem I’ve set up two pretty much identical extension functions in the bean info class.

[code] List extfnlist = new ArrayList();
ExtensionFunctionDescriptor.Builder myBuilder = new ExtensionFunctionDescriptor.Builder(“onRowsDropped”);
myBuilder.description(“Called when the user has dropped rows on this component. Note that the rows may have come from this component or another component. The source component must have dragging enabled”);
myBuilder.arg(“source”, “A reference to the component that is calling this function”);
myBuilder.arg(“rows”, “An array of the indices of the rows being dropped”);
myBuilder.arg(“rowData”, “A dataset containing the data that is being dropped”);
myBuilder.arg(“dropIndexLocation”, “The index of the row at which the data is being dropped”);
myBuilder.defaultImpl("");
myBuilder.returns(void.class);
extfnlist.add(myBuilder.build());

    myBuilder = new ExtensionFunctionDescriptor.Builder("onRowsDropped2");
    myBuilder.description("Called when the user has dropped rows on this component.  Note that the rows may have come from this component or another component.  The source component must have dragging enabled");
    myBuilder.arg("source", "A reference to the component that is calling this function");
    myBuilder.arg("rows", "An array of the indices of the rows being dropped");
    myBuilder.arg("rowData", "A dataset containing the data that is being dropped");
    myBuilder.arg("dropIndexLocation", "The index of the row at which the data is being dropped");
    myBuilder.defaultImpl("");
    myBuilder.returns(void.class);
    extfnlist.add(myBuilder.build());
    
    bean.setValue(ExtensionFunctionDescriptor.EXTENSION_FUNCTIONS, extfnlist);[/code]

The display within the “scripting” dialog of “onRowsDropped” and “onRowsDropped2” are respectively:


and


The difference between the two functions is that “onRowsDropped” is installed into the list of available extension functions within the component itself and “onRowsDropped2” is not installed. Any ideas on what I’m doing to offend the faceless men and the multi-faced god that they would treat me so?

[code] extensionFunctions = new HashMap<String, ExtensionFunction>();
extensionFunctions.put(“onRowsDropped”, onRowsDropped);

}   ------------- this is the end of the component constructor

@Override
public void onStartup() {
    super.onStartup(); 
}

Map<String, ExtensionFunction> extensionFunctions = null;
private final ExtensionFunction onRowsDropped = 
        new ExtensionFunction(false, "");;

@Override
public Map<String, ExtensionFunction> getExtensionFunctions() {
    return extensionFunctions;
}

@Override
public void setExtensionFunctions(Map<String, ExtensionFunction> map) {
    this.extensionFunctions = map;
}[/code]

Have you tried not reusing the variable myBuilder? We tend to use this style internally:

[code]extensions.add(ExtensionFunctionDescriptor
.newFunction(“extFunc1”)
.returns(Boolean.class)
.description(“Our first function”)
.arg(“a”, “An argument”)
.arg(“b”, “Another arg.”)
.defaultImpl(“return 1”)
.build());

	extensions.add(ExtensionFunctionDescriptor
					.newFunction("extFunc2")
					.returns(Void.class)
					.description("Does something else")
					.arg("x", "Some number")
					.build());

[/code]

I’ll give it a try. But, I suspect it won’t fix it as the problem was there before I included the second function. I included the second function just to illustrate the problem only occurred after I had created the reference to the extension function in myComponent.

I’m afraid it didn’t work, but thanks for the suggestion.

Seems like I have to define the default implementation of my extension function within the component body. The text in the script parameter to the ExtensionFunction constructor is overwriting what is generated by the BeanInfo class.

Map<String, ExtensionFunction> extensionFunctions = null; private final ExtensionFunction onRowsDropped = new ExtensionFunction(false, "def onRowsDropped(self, source, rows, rowData, dropIndexLocation):\n" + "\t\"\"\"\n" + "\tCalled when the user has dropped rows on this component.\n" + "\n" + "\tArguments:\n" + "\t\tself: A reference to the component that is invoking this function\n" + "\t\tsource: A reference to the component containing the source data\n" + "\t\trows: An array of the indices of the rows being dropped\n" + "\t\trowData: A dataset containing the data that is being dropped\n" + "\t\tdropIndexLocation: The index of the row at which the data is being dropped\n" + "\t\"\"\"\n" );

I’m missing something I’m sure.

Even worse. Any python script that I attach as an “onRowsDropped” extension function within the designer is not being retained when I restart the designer.

Why are you doing this?

extensionFunctions = new HashMap<String, ExtensionFunction>(); extensionFunctions.put("onRowsDropped", onRowsDropped);

That’s the reason your “onRowsDropped” extension function looks “empty” because you are building it yourself here:

private final ExtensionFunction onRowsDropped = new ExtensionFunction(false, "");;

You aren’t supposed to do that. Let the system build that extension function instance for you if the user ends up enabling that extension function.

I now can see why an experienced person would see it as a silly thing to do.

The fact that I initialized the property variable extensionFunctions ensured that when I restarted the designer any extension function that I had saved got lost as well.

Revised code works like a charm, thanks :prayer: Carl

[code] //extensionFunctions = new HashMap<String, ExtensionFunction>();
//extensionFunctions.put(“onRowsDropped”, onRowsDropped);
}

Map<String, ExtensionFunction> extensionFunctions;[/code]

:thumb_left: