# Java

Source: https://docs.interop.io/desktop/capabilities/app-management/java/index.html

## Listing Apps

To list all apps available to the current user, use the `applications()` method:

```java
io.appManager().applications();
```

The `applications()` method returns a `Map<String, ApplicationInstance>` result containing the available app instances keyed by app name.

## Starting Apps

To start an app, use the `start()` method:

```java
io.appManager().start("clientlist")
        .whenComplete((instance, error) -> {
            if (error != null) {
                // App failed to start.
            }
        });
```

You can also pass a context object (an app-specific object that will be available in the new app) or override any of the pre-configured window settings:

```java
io.appManager().start("clientcontact", Collections.singletonMap("selectedUser", 2));
```

## Listing Running Instances

To list all running app instances, use the `instances()` method:

```java
Collection<ApplicationInstance> allInstances = io.appManager().instances();
```

## Current Instance

To retrieve the current app instance, use the `myInstance()` method:

```java
Optional<ApplicationInstance> myInstance = io.appManager().myInstance();
```

## Stopping Instances

To stop a running instance, use the `close()` or `closeAsync()` method:

```java
instance.closeAsync();
```

## Events

### Shutdown

The shutdown event provided by the App Management API allows you to execute custom code before **io.Connect Desktop** shuts down. The available time for the execution of your code is 60 seconds.

The handler accepts a `ShuttingDownArguments` object as an argument, which you can use to determine whether **io.Connect Desktop** is shutting down or restarting. The handler must return a stage completed with a Boolean value indicating whether shutdown should be prevented or not.

```java
ShuttingDownHandler handler = shuttingDownArguments -> {
    // Check whether io.Connect Desktop is restarting.
    boolean restarting = shuttingDownArguments.isRestarting();
    boolean prevent = false;

    if (restarting) {
        System.out.println("Restarting...");
    } else {
        // Indicate that shutdown must be prevented.
        prevent = true;
    }

    return CompletableFuture.completedFuture(prevent);
};

// Register the shutdown handler.
io.appManager().registerShuttingDownHandler(handler);
```

## Multi Window Apps

io.Connect Java offers support for apps consisting of multiple windows. Each child window of an app can be registered as an io.Connect app that you can save and restore in a [Layout](https://docs.interop.io/desktop/capabilities/windows/layouts/overview/index.md), start directly from the io.Connect launcher, and more. This feature allows you to register Java windows dynamically and to properly persist their state when saving and restoring a Layout.

> ⚠️ *Note that for your main window to be able to register its child windows, the **io.Connect Desktop** [in-memory app store](https://docs.interop.io/desktop/developers/configuration/system/index.md#app_stores-inmemory) must be enabled.*

The following example demonstrates how to register an `ApplicationInstanceHandler` using the `registerInstanceHandler()` method. It will be invoked when a child window of the specified app is started. The handler in the example registers the child window as an io.Connect Window (for more details, see [Window Management](https://docs.interop.io/desktop/capabilities/windows/window-management/java/index.md)) using a `WindowRegistration` builder. When the child window has been registered, it starts to listen for context updates using its `onContextUpdated()` method. Finally, when a [Layout](https://docs.interop.io/desktop/capabilities/windows/layouts/java/index.md) save is requested, the child window will save its current context using the `addSaveListener()` method in order to be able to retrieve it later when the Layout is restored:

```java
io.appManager().registerInstanceHandler("my-child-window", appInstance -> {

    io.windows().register(
            WindowRegistration.builder(io.windows().getWindowHandle(childFrame))
                    .withInstanceId(appInstance.getId())
                    .build()
    ).thenAccept(window ->
            window.onContextUpdated(e ->
                selector.setSelectedIndex(selectedIndex);
            {
                int selectedIndex = (Integer) e.getContext().getOrDefault("SelectedIndex", -1);
            }));
    io.layouts().addSaveListener(appInstance.getId(), request ->
            Collections.singletonMap("SelectedIndex", selector.getSelectedIndex()));
});
```
