JMRI: Application Structure
Author: Bob Jacobsen
Keywords: JMRI technical code

# JMRI Code: Application Structure

This page discusses the structure of JMRI application(s). For the structure of the JMRI library itself, see the Introduction to JMRI Library Structure page. JMRI ships with several main "applications":

DecoderPro
  From `apps.gui3.dp3.DecoderPro3`: This is an example of a "new structure" application.
PanelPro
  From `apps.PanelPro.PanelPro`: This is an example of a "original structure" application.
JmriFaceless
  From `app.JmriFaceless`, this is a version of PanelPro that's been optimized to run on computers without displays and mice, i.e. a Raspberry PI. It uses the original structure.

## New Application Structure

The currently-recommended application form had the main application class descending from the `apps.gui3.Apps3` class.

Most of the required customization for a new application consists of overriding apps.Apps methods that control the display during startup: providing the main image, name and program link, etc.

Beyond that, the new application class can override implementations that create menus, load help, configure preferences, etc.

The startup sequence for e.g. DecoderPro, starting with `DecoderPro#main(..)` is quite short:

    public static void main(String args[]) {
        preInit(args);
        DecoderPro3 app = new DecoderPro3(args);
        app.start();
    }

    static public void preInit(String[] args) {
        apps.gui3.Apps3.preInit(applicationName);
        setConfigFilename("DecoderProConfig3.xml", args);
    }

- `apps.gui3.Apps3.preInit` initializes conditions for basic running: set up logging, set up the console, etc.
- `apps.gui3.Apps3.setConfigFilename` sets the filename (pathname) for the configuration file, either from system properties, launch arguments, or if needed from a default argument.
- The DecoderPro constructor just refers up to the App3 constructor, which in turn handles some GUI initiatlization and relies on the AppsBase constructor for the rest.
- Apps3.start() is then responsible for the program's dynamics.

Some useful milestones:

Windows, toolbars and menus
  The Gui3 support (see the JMRI Swing page) is used to define toolsbars and menus. For example, `apps.gui3.dp3.DecoderPro3#getMenuFile()` loads from `xml/config/parts/jmri/jmrit/roster/swing/RosterFrameMenu.xml` and `apps.gui3.dp3.DecoderPro3#getToolbarFile()` loads from `xml/config/parts/jmri/jmrit/roster/swing/RosterFrameToolBar.xml`
Load configuration
  `apps.AppsBase.jmri.ConfigureManager()` loads the configuration file, and in the process loads and activates many of the user level objects in the system. In particular, this is the start of loading the system connections.

For more information, see the `apps.gui3.Apps3` Javadoc.

## Older Application Structure

The older, original application form had the main application class descending from the `apps.Apps` class.

Most of the required customization for a new application consists of overriding apps.Apps methods that control the display during startup: providing the main image, name and program link, etc.

Beyond that, the new application class can override implementations that create menus, load help, configure preferences, etc.

The startup sequence for e.g. PanelPro, is then:

1. `PanelPro#main(..)` starts and does some initial interactions by invoking methods from `apps.Apps`
2. It then constructs a `PanelPro` object, most of whose behavior is inherited from `apps.Apps`.
3. Finally, it uses the `apps.Apps#createFrame` method to complete the setup.

For more information, see the `apps.Apps` Javadoc.

## Minimal Application Structure

(This may be out of date)

The apps.SampleMinimalProgram class provides a minimal example of starting a program that uses JMRI. It's got a hard-coded layout configuration. See the internal comments for more info.

The preferred way is to use the JMRI configuration system to read a configuration file and do the initialization. There's commented out code in apps.SampleMinimalProgram that shows how to do that.

The JMRI applications themselves use a more powerful "profile" mechanism that's inherited from the apps.Apps and apps.AppsBase classes.