# I am looking for a tutor for module development

**URL:** <https://forum.inductiveautomation.com/t/i-am-looking-for-a-tutor-for-module-development/55030>\
**Category:** Module Development\
**Tags:** ignition80\
**Created:** [January 14, 2022, 3:18pm UTC](https://forum.inductiveautomation.com/t/i-am-looking-for-a-tutor-for-module-development/55030 "2022-01-14T15:18:39Z")\
**Posts on this page:** 1\
**Showing post:** 4

<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:** [January 14, 2022, 5:12pm UTC](https://forum.inductiveautomation.com/t/i-am-looking-for-a-tutor-for-module-development/55030/4 "2022-01-14T17:12:13Z")

</div>

> [@bkarabinchak.psi](#):
>
> Again apologies if this breaks any terms of this forum but I can’t think of a better pool of people who might be able to help me out with learning this.

Nah, you're fine. We have occasional job posts/job seekers as well; I think as long as they're not inundating the forum it's not a big deal.

I think at least part of the confusion for people who might be familiar with _programming_, but struggle to get started with module development, is that you're learning two separate things at the same time.  
There's a particular Java build stack (whether you choose Maven or Gradle or whatever), and then attached to it the Ignition API surface, which is fairly massive.

It's also a problem from the other direction: people tell us they want a 'module development' course, but it's almost impossible to target everyone's experience with the different aspects.

I guess I'll start with some very high level principles.  
Your build system of choice (_generally_ Gradle or Maven, there's other options but they're certainly the most common these days) is usually in charge of running the Java compiler over your Java source files to generate a jar file. JAR files are just ZIPs full of .class files, which are themselves _essentially_ just JVM bytecode. That's an important point of distinction - once it's a class file, it's not technically Java anymore. That's part of how alternate JVM languages like Kotlin and Scala work - they just have to emit valid bytecode, without the limitations of Java's own syntax and compiler. (There are also tools available to 'decompile' bytecode back to ~the input Java code, but there's always information lost, such as parameter names for method and other issues. IntelliJ has a pretty good decompiler built in, which can help to look into library code you don't have the underlying source for).

By **convention** , Maven (the big kahuna Java build system for a long time) looks for Java files to compile in `src/main/java`. Every directory under that root _by convention_ defines your package structure. Package structure is important, because there's a single global namespace in the final JVM - every class must have a unique fully-qualified name. _By convention_, the package name you use should be a reversed domain name that you control - that allows you to "prove" that you wrote the code, and is useful for library distribution (and part of the verification process on repositories like Maven Central). Gradle follows these conventions precisely because Maven was dominant for such a long time. However, in both Maven and Gradle, you _can_ readily change these things (it's just generally not a good idea unless you have a good reason).

Separate from the actual source file organization, you can organize your projects themselves into "subprojects" (what Gradle calls them, Maven may have a different name). Basically these are just folders at the top-level that contain their own build-system descriptors (`build.gradle(.kts)`/`pom.xml`). Somewhere on the top level, you'll define which subprojects you have, and your build system will automatically reach into those subfolders and build _their_ projects too.  
For instance, in the [Perspective Component example](https://github.com/inductiveautomation/ignition-sdk-examples/tree/master/perspective-component), there's four subprojects: `common`, `designer`, `gateway`, and `web`. Those are outlined in the [`settings.gradle`](https://github.com/inductiveautomation/ignition-sdk-examples/blob/master/perspective-component/settings.gradle) at the root.

So that's the _very_ broad overview of Java building. Pivoting a little to Ignition:

That `common`/`gateway`/`designer` split is a common _convention_ in the realm of Ignition, because 1. code re-use is nice, and 2. you almost always want to deliver different artifacts to the different Ignition scopes (because they have different APIs and different capabilities). So you build those subprojects, and each outlines their own dependencies on Ignition; e.g. `common` depends on Ignition's own `common` layer: [https://github.com/inductiveautomation/ignition-sdk-examples/blob/master/perspective-component/common/build.gradle#L12](https://github.com/inductiveautomation/ignition-sdk-examples/blob/master/perspective-component/common/build.gradle#L12)  
And then `gateway` can depend on both Ignition specific `gateway` apis **and the `common` subproject** :  
[https://github.com/inductiveautomation/ignition-sdk-examples/blob/master/perspective-component/gateway/build.gradle#L10](https://github.com/inductiveautomation/ignition-sdk-examples/blob/master/perspective-component/gateway/build.gradle#L10)  
_That_ is how you tell the build system (and your IDE) "this code I'm writing in `gateway` can use anything I've written in `common`.

The _only_ fundamental unit you need to provide as a module is _some_ implementation of the appropriate hook class for your desired scope. Basically, you author a class that implements the \*Hook (or, better extends the abstract class we provide) for the right scope, e.g. `AbstractGatewayModuleHook` for the gateway:

> <https://github.com/inductiveautomation/ignition-sdk-examples/blob/master/perspective-component/gateway/src/main/java/org/fakester/gateway/RadGatewayHook.java>

There are various lifecycle methods that will be invoked _for you_ - `setup`, `startup`, and `shutdown`. Those are how your module gets access to the rest of Ignition - from the GatewayContext you get in `setup`, you can get access to the myriad subsystems available in Ignition.

However, just implementing the class and putting it into a jar file isn't enough. Ignition doesn't "know" enough to know how to actually do anything with one or more plain .jar files. So there's one final piece - the actual module .modl file. The actual module file is nothing more than a ZIP file that contains a bunch of .jar files and a `module.xml` file. That `module.xml` file is crucial - it tells Ignition _how_ to load your various jar files, what scopes they belong to, and most importantly, what your actual hook classes are:

```python
<?xml version="1.0" encoding="UTF-8"?>
<modules>
	<module>
		<id>com.inductiveautomation.ignition.examples.hce</id>
		<name>Gateway Webpage Example</name>
		<description>Implements a fake "Home Connect" hub status and configuration page</description>
		<version>1.0.0-SNAPSHOT</version>
		<requiredignitionversion>8.1.0-SNAPSHOT</requiredignitionversion>
		<depends scope="G">com.inductiveautomation.opcua</depends>
		<jar scope="G">gateway-webpage-gateway-1.0.0-SNAPSHOT.jar</jar>
		<hook scope="G">com.inductiveautomation.ignition.examples.hce.GatewayHook</hook>
	</module>
</modules>

```

Generating these XML files by hand would be annoying, which is why we provide Maven and Gradle plugins to build modules for you. The 'new' generation is available [here](https://github.com/inductiveautomation/ignition-module-tools), and is the exact same tool we use internally.  
Your build system of choice should provide a place to configure this plugin, e.g. Gradle:  
[https://github.com/inductiveautomation/ignition-sdk-examples/blob/master/perspective-component/build.gradle#L34](https://github.com/inductiveautomation/ignition-sdk-examples/blob/master/perspective-component/build.gradle#L34)  
or Maven:

> <https://github.com/inductiveautomation/ignition-sdk-examples/blob/master/report-component/report-component-build/pom.xml#L36>

I just kinda rambled that all out, and my hand hurts now, but hopefully that helps a bit to orient.

If you've got particular questions on _how_ to approach something in Ignition, I'd definitely say to ask here on the forums. More general build system questions might be better suited for other places, but it doesn't really hurt to ask here either.

---

_[View the full topic](https://forum.inductiveautomation.com/t/i-am-looking-for-a-tutor-for-module-development/55030)._
