Module Development Example Question

I am thinking of making a more thorough database connection + scripting examples module tutorial similar to my Perspective component example.

I am soliciting ideas for possibly useful examples outside of the following:

  • The ability to have multiple pooled connections to different databases
  • Script functions to perform CRUD operations,
  • A wicket page for the database connection persistent records,
  • Managing a third party jar in a module
  • Very thorough docs like my other one explaining all the files, build structure, etc.,

(Note I recognize the wicket and config stuff will be totally different in 8.3, but I already have examples of this from an old neo4j module I made, so it’s relatively low effort for anyone trapped in 8.1 long term)

A few “nice to haves” I thought of

  • Query Browser,
  • “Named query” style resources
  • Status Page in Gateway (also I have an example, so low-ish effort, even though wicket)

Lastly, I am probably going to do it in Redis, feels like the lowest hanging fruit example with a friendly-ish Java library.

I am open to thoughts for additional features that would be useful to explain

I would like to see an example of how to extend the 8.3 REST API for a custom module and have it show up in the /openapi documentation. If this is even possible.

Maybe something like this:

GET /data/api/v1/resources/list/<custom_module_id>/hello-world

Bonus if you can show how to integrate the X-Ignition-API-Token for authenticating requests.

Contributing to the central OpenAPI definition from a module is very easy.

Just override/implement mountRouteHandlers in your module's gateway hook. The Route class we provide has an OpenAPI builder attached to it you can use to build up a response.

    @Override
    public void mountRouteHandlers(RouteGroup routes) {
        routes.newRoute("/api/v1/session/:sessionId/pages")
            .type(RouteGroup.TYPE_JSON)
            .method(HttpMethod.GET)
            .requirePermission(PermissionType.READ)
            .itemListHandler(this::getSessionPages)
            .itemSerializer(gson)
            .itemSchema(SchemaUtil.fromType(PerspectivePageInfo.class))
            .openApi(api -> api
                .tag(SESSION_TAG)
                .summary("Perspective Pages")
                .description("Retrieves a list of all pages in a session.")
                .pathParameter("sessionId", "ID of the session", JsonType.STRING, null)
                .response(SC_NOT_FOUND, "The session ID does not exist"))
            .mount();

By default, routes added in this way will be exposed under $host/data/$yourModuleId/$whateverRouteMountingPath - so in the example above, you would
POST http://localhost:8088/data/myModuleId/someName

You can override getMountPathAlias on your gateway hook to replace yourModuleId with some shorter alias for friendlier URLs - you're just in charge of avoiding collisions then.

There isn't any directly supported way to add custom URLs within an existing prefix, such as resources, but you can add them to /api/v1/, just like a bunch of our first party modules do.
You should 'qualify' your additional methods as belonging to your module so it's clear to end users:

        routes.addOpenApiGroup("Perspective", SESSION_TAG);
        routes.addOpenApiGroup("Perspective", CONFIG_THEMES_TAG);

And as for:

You don't have to, if you use our route mounting system.
.requirePermission(PermissionType.READ) (or PermissionType.ACCESS/WRITE)
will automatically require the appropriate gateway access permission. If you really want to have a distinct meaning of permissions, it's certainly possible, but you're going to have an easier time if you stick to what we provide for you automatically.

Sorry to revive an old thread, but what happens if
multiple modules use the same route path alias? Is using a shared one across modules allowed?

It looks like subsequent modules trying to reuse an alias will encounter an IllegalArgumentException that causes the routes to fail to mount.