# Module Development Example Question

**URL:** <https://forum.inductiveautomation.com/t/module-development-example-question/107639>\
**Category:** Module Development\
**Tags:** perspective\
**Created:** [June 20, 2025, 8:56pm UTC](https://forum.inductiveautomation.com/t/module-development-example-question/107639 "2025-06-20T20:56:14Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![kgamble](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kgamble/32/8019_2.png) [@kgamble](https://forum.inductiveautomation.com/u/kgamble)\
**Post date:** [June 20, 2025, 8:56pm UTC](https://forum.inductiveautomation.com/t/module-development-example-question/107639/1 "2025-06-20T20:56:14Z")

</div>

I am thinking of making a more thorough database connection + scripting examples module tutorial similar to my [Perspective component example](https://github.com/keith-gamble/example-perspective-component-module).

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

---

<div class="post-metadata">

**Author:** ![Nathan\_Foster](https://avatars.discourse-cdn.com/v4/letter/n/ecd19e/32.png) [@Nathan\_Foster](https://forum.inductiveautomation.com/u/Nathan_Foster)\
**Post date:** [September 12, 2025, 2:26pm UTC](https://forum.inductiveautomation.com/t/module-development-example-question/107639/2 "2025-09-12T14:26:49Z")

</div>

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.

---

<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:** [September 12, 2025, 4:06pm UTC](https://forum.inductiveautomation.com/t/module-development-example-question/107639/3 "2025-09-12T16:06:51Z")

</div>

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.

```java
    @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:

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

```

And as for:

> [@Nathan\_Foster](#):
>
> Bonus if you can show how to integrate the X-Ignition-API-Token for authenticating requests.

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.

---

<div class="post-metadata">

**Author:** ![Ethan\_Brown](https://avatars.discourse-cdn.com/v4/letter/e/9de053/32.png) [@Ethan\_Brown](https://forum.inductiveautomation.com/u/Ethan_Brown)\
**Post date:** [February 19, 2026, 1:43am UTC](https://forum.inductiveautomation.com/t/module-development-example-question/107639/4 "2026-02-19T01:43:18Z")

</div>

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?

---

<div class="post-metadata">

**Author:** ![Kevin.Herron](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kevin.herron/32/7259_2.png) [@Kevin.Herron](https://forum.inductiveautomation.com/u/Kevin.Herron)\
**Post date:** [February 19, 2026, 2:03am UTC](https://forum.inductiveautomation.com/t/module-development-example-question/107639/5 "2026-02-19T02:03:27Z")

</div>

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