Ignition Settings Next Page

I don’t see an obvious problem. I do see that you haven’t made your record types serializable. Pretty sure that isn’t optional.

Okay thanks, Ill wait and see what @PGriffith says, he got me this far lol!

I think

    @Override
    public @Nullable ExtensionPointType getExtensionPoint(String typeId) {
        return null;
    }

Should be a switch on typeId mapping "MIR" and "OTTO" to your different extension point types - that way, when you try to create a new record, it creates a new extension point type, and that new extension point type creates the actual record.

And, I don't think your subtype actually has to extend SCMBaseType. Internally we usually use an abstract base type that handles the description/name key, so the subclass only has to pass in a type ID, but that's mostly up to you.

OK thank you. Whats the point of this field?

I have created these:

If i goto edit them, the user could choose from this drop down, or edit the extension type itself. I feel like I should be hiding that drop down from the user?

Yes, you want to make the profile (and type, on the base record) invisible; in a static block in the record class do something like this:

Type.getFormMeta().setVisible(false);
1 Like

Awesome. Now just the refactoring needs done :stuck_out_tongue:

So I am querying the base record, then I get the type and check it equals the “MIR” type.

I then need the associated MirSettingsRecord with that type… how would I ensure I get the right one?

SQuery<SCMBaseRecord> query = new SQuery<>(SCMBaseRecord.META); 
List<SCMBaseRecord> results = context.getPersistenceInterface().query(query);

for (int i = 0; i < results.size(); i++) {
        if (results.get(i).getType().equals("MIR")) {

What I would do is follow the model we use internally. Your ‘manager’ queries all the (base) records on startup, then finds their type. Then each ExtensionPointType you’ve created defines a ‘createNewInstance’ method (that accepts a base record), and uses the findProfileSettingsRecord method on ExtensionPointType to get its own “subrecord”. Then you feed the values from the base and the subrecord into your actual extension point class’ constructor.

Sorry I am confused. Are you describing how the ExternsionPointManager works?

I though the extensionPointManager was only called via the ExtensionPointPage. Are you saying I need to somehow register the extensionPointManager in the gateway first?

No.
Whatever manager class you’re already creating in your module’s GatewayHook should be the class that implements ExtensionPointManager. On startup, it runs the query to find all the SCMBaseRecords in the database. For each of those records, it will pull out the type field, then run getExtensionPoint to retrieve the specific ExtensionPointType of each of your types of subrecords. You should add an abstract base class (extending BaseExtensionPointType) that defines a createNewInstance(GatewayContext context, SCMBaseRecord record) method. Then the manager, while it’s going through the list of records, can call createNewInstance on each record in the database to create the new instances. To retrieve the subrecord’s individual records, you use findProfileSettingsRecord inside the createNewInstance function.

So manager starts up, finds all the records. Finds the extension point, then asks each extension point to create itself, providing the base record. Each extension point can use its base record to find it’s ‘child’ record, and then use those together to create its instance, and hand that back to the ‘manager’, so that the manager can run whatever other bookkeeping it needs to.

I have this as my base class.

@SuppressWarnings(“serial”)
public class SCMBaseType extends BaseExtensionPointType {
public SCMBaseType(String typeId, String nameKey, String descriptionKey) {
super(typeId, nameKey, descriptionKey);
}

@Override
public RecordMeta<? extends PersistentRecord> getSettingsRecordType() {
    return SCMBaseRecord.META;
}

}

Is this were I put the createNewInstance function? and then do I extend MirExtensionType and OTTOExtensionType off of this base class?

Yes, exactly.

Ok. So then here I am.

Now this may break… wouldn’t findProfileSettingsRecord return a MirSettingsRecord or an OTTOSettingsRecord here?

At this point it is working.

My last problem is this:

I am returning a new SCMExtensionPointManager() in my ExtensionPoint Page Class

@SuppressWarnings(“serial”)
public class SCMBaseSettingsPage extends ExtensionPointPage {

public static final Pair<String, String> MENU_LOCATION = Pair.of(GatewayHook.CONFIG_CATEGORY.getName(), "mirconfig");

public SCMBaseSettingsPage(IConfigPage configPage) {
    super(configPage);
}

@Override
protected ExtensionPointManager getExtensionPointManager() {
    return new SCMExtensionPointManager();
}

@Override
public Pair<String, String> getMenuLocation() {
    return MENU_LOCATION;
}

@Override
protected RecordMeta<SCMBaseRecord> getRecordMeta() {
    return SCMBaseRecord.META;
}

}

I am also declaring a new SCMExtensionPointManager instance in my gateway, so I can call it’s startup and shutdown methods when appropriate.

Shouldn’t I be using only one instance here? if so, what the recommended way of doing this?

You're not fully implementing things.
createNewInstance should be returning a concrete instance of whatever base actual thing MirSettingsRecord or OTTOSettingsRecord map to - a MirInstance() or OTTOInstance(), which take as constructor parameters an SCMSettingsRecord and a MirSettingsRecord/OTTOSettingsRecord, as appropriate. findProfileSettingsRecord is just a convenience method to do the foreign key lookup from the SCMBaseRecord that's provided - you then need to use the parent and child record together, and actually pass them in to your constructed object.

The easiest way is to use the singleton pattern (Design Pattern - Singleton Pattern). You could even have your GatewayHook be the singleton, if you want; it just has to implement the ExtensionPointManager methods. But you definitely should not be creating new instances.

Great. Implemented Singleton, and updated createNewInstance(). This is only my second large java project. I am mainly a python guy so this has been a fun learning curve.

At this point it is working well. I am going to throw together a tutorial in the forums for any future goers.

Thank you!

2 Likes

Probably should have just done this earlier, but I threw together a full example:

1 Like

Great :slight_smile: saves me the time ahaha

The original cause of this thread has been solved, but I could see the answer to this question being relevant to anyone implementing this page, so asking here.

How do you make the ExtensionPointPage poll/refresh one of the values on-screen for each record?

For instance on the Database Connections Config page the "Status" column is polling every X seconds.

I don't see a column doing that in the example you made @PGriffith