# Elixir v1.10.3 Application behaviour View Source

A module for working with applications and defining application callbacks.

Applications are the idiomatic way to package software in Erlang/OTP. To get the idea, they are similar to the "library" concept common in other programming languages, but with some additional characteristics.

An application is a component implementing some specific functionality, with a standardized directory structure, configuration, and lifecycle. Applications are loaded, started, and stopped. Each application also has its own environment, which provides a unified API for configuring each application.

Developers typically interact with the application environment and its callback module. Therefore those will be the topics we will cover first before jumping into details about the application resource file and life-cycle.

## The application environment

Each application has its own environment. The environment is a keyword list that maps atoms to terms. Note that this environment is unrelated to the operating system environment.

By default, the environment of an application is an empty list. In a Mix project's `mix.exs` file, you can set the `:env` key in `application/0`:

    def application do
      [env: [db_host: "localhost"]]
    end

Now, in your application, you can read this environment by using functions such as `fetch_env!/2` and friends:

    defmodule MyApp.DBClient do
      def start_link() do
        SomeLib.DBClient.start_link(host: db_host())
      end

      defp db_host do
        Application.fetch_env!(:my_app, :db_host)
      end
    end

In Mix projects, the environment of the application and its dependencies can be overridden via the `config/config.exs` file. For example, someone using your application can override its `:db_host` environment variable as follows:

    import Config
    config :my_app, :db_host, "db.local"

You can also change the application environment dynamically by using functions such as `put_env/3` and `delete_env/2`. However, as a rule of thumb, each application is responsible for its own environment. Please do not use the functions in this module for directly accessing or modifying the environment of other applications.

### Compile-time environment

In the previous example, we read the application environment at runtime:

    defmodule MyApp.DBClient do
      def start_link() do
        SomeLib.DBClient.start_link(host: db_host())
      end

      defp db_host do
        Application.fetch_env!(:my_app, :db_host)
      end
    end

In other words, the environment key `:db_host` for application `:my_app` will only be read when `MyApp.DBClient` effectively starts. While reading the application environment at runtime is the preferred approach, in some rare occasions you may want to use the application environment to configure the compilation of a certain project. This is often done by calling `get_env/3` outside of a function:

    defmodule MyApp.DBClient do
      @db_host Application.get_env(:my_app, :db_host, "db.local")

      def start_link() do
        SomeLib.DBClient.start_link(host: @db_host)
      end
    end

This approach has one big limitation: if you change the value of the application environment after the code is compiled, the value used at runtime is not going to change! For example, if you are using `mix release` and your `config/releases.exs` has:

    config :my_app, :db_host, "db.production"

This value will have no effect as the code was compiled to connect to "db.local", which is mostly likely unavailable in the production environment.

For those reasons, reading the application environment at runtime should be the first choice. However, if you really have to read the application environment during compilation, we recommend you to use `compile_env/3` instead:

    @db_host Application.compile_env(:my_app, :db_host, "db.local")

By using `compile_env/3`, tools like Mix will store the values used during compilation and compare the compilation values with the runtime values whenever your system starts, raising an error in case they differ.

## The application callback module

Applications can be loaded, started, and stopped. Generally, build tools like Mix take care of starting an application and all of its dependencies for you, but you can also do it manually by calling:

    {:ok, _} = Application.ensure_all_started(:some_app)

When an application starts, developers may configure a callback module that executes custom code. Developers use this callback to start the application supervision tree.

The first step to do so is to add a `:mod` key to the `application/0` definition in your `mix.exs` file. It expects a tuple, with the application callback module and start argument (commonly an empty list):

    def application do
      [mod: {MyApp, []}]
    end

The `MyApp` module given to `:mod` needs to implement the `Application` behaviour. This can be done by putting `use Application` in that module and implementing the `c:start/2` callback, for example:

    defmodule MyApp do
      use Application

      def start(_type, _args) do
        children = []
        Supervisor.start_link(children, strategy: :one_for_one)
      end
    end

The `c:start/2` callback has to spawn and link a supervisor and return `{:ok, pid}` or `{:ok, pid, state}`, where `pid` is the PID of the supervisor, and `state` is an optional application state. `args` is the second element of the tuple given to the `:mod` option.

The `type` argument passed to `c:start/2` is usually `:normal` unless in a distributed setup where application takeovers and failovers are configured. Distributed applications are beyond the scope of this documentation.

When an application is shutting down, its `c:stop/1` callback is called after the supervision tree has been stopped by the runtime. This callback allows the application to do any final cleanup. The argument is the state returned by `c:start/2`, if it did, or `[]` otherwise. The return value of `c:stop/1` is ignored.

By using `Application`, modules get a default implementation of `c:stop/1` that ignores its argument and returns `:ok`, but it can be overridden.

Application callback modules may also implement the optional callback `c:prep_stop/1`. If present, `c:prep_stop/1` is invoked before the supervision tree is terminated. Its argument is the state returned by `c:start/2`, if it did, or `[]` otherwise, and its return value is passed to `c:stop/1`.

## The application resource file

In the sections above, we have configured an application in the `application/0` section of the `mix.exs` file. Ultimately, Mix will use this configuration to create an application resource file, which is a file called `APP_NAME.app`. For example, the application resource file of the OTP application `ex_unit` is called `ex_unit.app`.

You can learn more about the generation of application resource files in the documentation of `Mix.Tasks.Compile.App`, available as well by running `mix help compile.app`.

## The application lifecycle

### Loading applications

Applications are loaded, which means that the runtime finds and processes their resource files:

    Application.load(:ex_unit)
    #=> :ok

When an application is loaded, the environment specified in its resource file is merged with any overrides from config files.

Loading an application does not load its modules.

In practice, you rarely load applications by hand because that is part of the start process, explained next.

### Starting applications

Applications are also started:

    Application.start(:ex_unit)
    #=> :ok

Once your application is compiled, running your system is a matter of starting your current application and its dependencies. Differently from other languages, Elixir does not have a `main` procedure that is responsible for starting your system. Instead, you start one or more applications, each with their own initialization and termination logic.

When an application is started, the `Application.load/1` is automatically invoked if it hasn't been done yet. Then, it checks if the dependencies listed in the `applications` key of the resource file are already started. Having at least one dependency not started is an error condition. Functions like `ensure_all_started/1` takes care of starting an application and all of its dependencies for you.

If the application does not have a callback module configured, starting is done at this point. Otherwise, its `c:start/2` callback if invoked. The PID of the top-level supervisor returned by this function is stored by the runtime for later use, and the returned application state is saved too, if any.

### Stopping applications

Started applications are, finally, stopped:

    Application.stop(:ex_unit)
    #=> :ok

Stopping an application without a callback module is defined, but except for some system tracing, it is in practice a no-op.

Stopping an application with a callback module has three steps:

1. If present, invoke the optional callback `c:prep_stop/1`.
2. Terminate the top-level supervisor.
3. Invoke the required callback `c:stop/1`.

The arguments passed to the callbacks are related to the state optionally returned by `c:start/2`, and are documented in the section about the callback module above.

It is important to highlight that step 2 is a blocking one. Termination of a supervisor triggers a recursive chain of children terminations, therefore orderly shutting down all descendant processes. The `c:stop/1` callback is invoked only after termination of the whole supervision tree.

Shutting down a live system cleanly can be done by calling `System.stop/1`. It will shut down every application in the opposite order they had been started.

By default, a SIGTERM from the operating system will automatically translate to `System.stop/0`. You can also have more explicit control over operating system signals via the `:os.set_signal/2` function.

## Tooling

The Mix build tool automates most of the application management tasks. For example, `mix test` automatically starts your application dependencies and your application itself before your test runs. `mix run --no-halt` boots your current project and can be used to start a long running system. See `mix help run`.

Developers can also use `mix release` to build releases. Releases are able to package all of your source code as well as the Erlang VM into a single directory. Releases also give you explicit control over how each application is started and in which order. They also provide a more streamlined mechanism for starting and stopping systems, debugging, logging, as well as system monitoring.

Finally, Elixir provides tools such as escripts and archives, which are different mechanisms for packaging your application. Those are typically used when tools must be shared between developers and not as deployment options. See `mix help archive.build` and `mix help escript.build` for more detail.

## Further information

For further details on applications please check the documentation of the `application` Erlang module, and the Applications section of the OTP Design Principles User's Guide.

# Link to this section Summary

## Types

app()
application_key()
key()
restart_type()
start_type()
state()
value()

## Functions

app_dir(app)

Gets the directory for app.

app_dir(app, path)

Returns the given path inside `app_dir/1`.

compile_env(app, key_or_path, default \\ nil)

Reads the application environment at compilation time.

compile_env!(app, key_or_path)

Reads the application environment at compilation time or raises.

delete_env(app, key, opts \\ [])

Deletes the `key` from the given `app` environment.

ensure_all_started(app, type \\ :temporary)

Ensures the given `app` and its applications are started.

ensure_loaded(app)

Ensures the given `app` is loaded.

ensure_started(app, type \\ :temporary)

Ensures the given `app` is started.

fetch_env(app, key)

Returns the value for `key` in `app`'s environment in a tuple.

fetch_env!(app, key)

Returns the value for `key` in `app`'s environment.

format_error(reason)

Formats the error reason returned by `start/2`, `ensure_started/2`, `stop/1`, `load/1` and `unload/1`, returns a string.

get_all_env(app)

Returns all key-value pairs for `app`.

get_application(module)

Gets the application for the given module.

get_env(app, key, default \\ nil)

Returns the value for `key` in `app`'s environment.

load(app)

Loads the given `app`.

loaded_applications()

Returns a list with information about the applications which have been loaded.

put_all_env(config, opts \\ [])

Puts the environment for multiple apps at the same time.

put_env(app, key, value, opts \\ [])

Puts the `value` in `key` for the given `app`.

spec(app)

Returns the spec for `app`.

spec(app, key)

Returns the value for `key` in `app`'s specification.

start(app, type \\ :temporary)

Starts the given `app`.

started_applications(timeout \\ 5000)

Returns a list with information about the applications which are currently running.

stop(app)

Stops the given `app`.

unload(app)

Unloads the given `app`.

## Callbacks

config_change(changed, new, removed)

Callback invoked after code upgrade, if the application environment has changed.

prep_stop(state)

Called before stopping the application.

start(start_type, start_args)

Called when an application is started.

start_phase(phase, start_type, phase_args)

Starts an application in synchronous phases.

stop(state)

Called after an application has been stopped.

# Link to this section Types

Link to this type

# app()

View Source

## Specs

    app() :: atom()

Link to this type

# application_key()

View Source

## Specs

    application_key() ::
      :start_phases
      | :mod
      | :applications
      | :included_applications
      | :registered
      | :maxT
      | :maxP
      | :modules
      | :vsn
      | :id
      | :description

Link to this type

# key()

View Source

## Specs

    key() :: atom()

Link to this type

# restart_type()

View Source

## Specs

    restart_type() :: :permanent | :transient | :temporary

Link to this type

# start_type()

View Source

## Specs

    start_type() :: :normal | {:takeover, node()} | {:failover, node()}

Link to this type

# state()

View Source

## Specs

    state() :: term()

Link to this type

# value()

View Source

## Specs

    value() :: term()

# Link to this section Functions

Link to this function

# app_dir(app)

View Source

## Specs

    app_dir(app()) :: String.t()

Gets the directory for app.

This information is returned based on the code path. Here is an example:

    File.mkdir_p!("foo/ebin")
    Code.prepend_path("foo/ebin")
    Application.app_dir(:foo)
    #=> "foo"

Even though the directory is empty and there is no `.app` file it is considered the application directory based on the name "foo/ebin". The name may contain a dash `-` which is considered to be the app version and it is removed for the lookup purposes:

    File.mkdir_p!("bar-123/ebin")
    Code.prepend_path("bar-123/ebin")
    Application.app_dir(:bar)
    #=> "bar-123"

For more information on code paths, check the `Code` module in Elixir and also Erlang's module`:code`.

Link to this function

# app_dir(app, path)

View Source

## Specs

    app_dir(app(), String.t() | [String.t()]) :: String.t()

Returns the given path inside `app_dir/1`.

If `path` is a string, then it will be used as the path inside `app_dir/1`. If `path` is a list of strings, it will be joined (see `Path.join/1`) and the result will be used as the path inside `app_dir/1`.

## Examples

    File.mkdir_p!("foo/ebin")
    Code.prepend_path("foo/ebin")

    Application.app_dir(:foo, "my_path")
    #=> "foo/my_path"

    Application.app_dir(:foo, ["my", "nested", "path"])
    #=> "foo/my/nested/path"

Link to this macro

# compile_env(app, key_or_path, default \\ nil)

View Source (macro) (since 1.10.0)

## Specs

    compile_env(app(), key() | list(), value()) :: value()

Reads the application environment at compilation time.

Similar to `get_env/3`, except it must be used to read values at compile time. This allows Elixir to track when configuration values change between compile time and runtime.

The first argument is the application name. The second argument `key_or_path` is either an atom key or a path to traverse in search of the configuration, starting with an atom key.

For example, imagine the following configuration:

    config :my_app, :key, [foo: [bar: :baz]]

We can access it during compile time as:

    Application.compile_env(:my_app, :key)
    #=> [foo: [bar: :baz]]

    Application.compile_env(:my_app, [:key, :foo])
    #=> [bar: :baz]

    Application.compile_env(:my_app, [:key, :foo, :bar])
    #=> :baz

A default value can also be given as third argument. If any of the keys in the path along the way is missing, the default value is used:

    Application.compile_env(:my_app, [:unknown, :foo, :bar], :default)
    #=> :default

    Application.compile_env(:my_app, [:key, :unknown, :bar], :default)
    #=> :default

    Application.compile_env(:my_app, [:key, :foo, :unknown], :default)
    #=> :default

Giving a path is useful to let Elixir know that only certain paths in a large configuration are compile time dependent.

Link to this macro

# compile_env!(app, key_or_path)

View Source (macro) (since 1.10.0)

## Specs

    compile_env!(app(), key() | list()) :: value()

Reads the application environment at compilation time or raises.

This is the same as `compile_env/3` but it raises an ArgumentError if the configuration is not available.

Link to this function

# delete_env(app, key, opts \\ [])

View Source

## Specs

    delete_env(app(), key(), timeout: timeout(), persistent: boolean()) :: :ok

Deletes the `key` from the given `app` environment.

It receives the same options as `put_env/4`. Returns `:ok`.

Link to this function

# ensure_all_started(app, type \\ :temporary)

View Source

## Specs

    ensure_all_started(app(), restart_type()) ::
      {:ok, [app()]} | {:error, {app(), term()}}

Ensures the given `app` and its applications are started.

Same as `start/2` but also starts the applications listed under `:applications` in the `.app` file in case they were not previously started.

Link to this function

# ensure_loaded(app)

View Source (since 1.10.0)

## Specs

    ensure_loaded(app()) :: :ok | {:error, term()}

Ensures the given `app` is loaded.

Same as `load/2` but returns `:ok` if the application was already loaded.

Link to this function

# ensure_started(app, type \\ :temporary)

View Source

## Specs

    ensure_started(app(), restart_type()) :: :ok | {:error, term()}

Ensures the given `app` is started.

Same as `start/2` but returns `:ok` if the application was already started. This is useful in scripts and in test setup, where test applications need to be explicitly started:

    :ok = Application.ensure_started(:my_test_dep)

Link to this function

# fetch_env(app, key)

View Source

## Specs

    fetch_env(app(), key()) :: {:ok, value()} | :error

Returns the value for `key` in `app`'s environment in a tuple.

If the configuration parameter does not exist, the function returns `:error`.

Link to this function

# fetch_env!(app, key)

View Source

## Specs

    fetch_env!(app(), key()) :: value()

Returns the value for `key` in `app`'s environment.

If the configuration parameter does not exist, raises `ArgumentError`.

Important: if you are reading the application environment at compilation time, for example, inside the module definition instead of inside of a function, see `compile_env!/2` instead.

Link to this function

# format_error(reason)

View Source

## Specs

    format_error(any()) :: String.t()

Formats the error reason returned by `start/2`, `ensure_started/2`, `stop/1`, `load/1` and `unload/1`, returns a string.

Link to this function

# get_all_env(app)

View Source

## Specs

    get_all_env(app()) :: [{key(), value()}]

Returns all key-value pairs for `app`.

Link to this function

# get_application(module)

View Source

## Specs

    get_application(atom()) :: atom() | nil

Gets the application for the given module.

The application is located by analyzing the spec of all loaded applications. Returns `nil` if the module is not listed in any application spec.

Link to this function

# get_env(app, key, default \\ nil)

View Source

## Specs

    get_env(app(), key(), value()) :: value()

Returns the value for `key` in `app`'s environment.

If the configuration parameter does not exist, the function returns the `default` value.

Important: if you are reading the application environment at compilation time, for example, inside the module definition instead of inside of a function, see `compile_env/3` instead.

Important: if you are writing a library to be used by other developers, it is generally recommended to avoid the application environment, as the application environment is effectively a global storage. For more information, read our library guidelines.

## Examples

`get_env/3` is commonly used to read the configuration of your OTP applications. Since Mix configurations are commonly used to configure applications, we will use this as a point of illustration.

Consider a new application `:my_app`. `:my_app` contains a database engine which supports a pool of databases. The database engine needs to know the configuration for each of those databases, and that configuration is supplied by key-value pairs in environment of `:my_app`.

    config :my_app, Databases.RepoOne,
      # A database configuration
      ip: "localhost",
      port: 5433

    config :my_app, Databases.RepoTwo,
      # Another database configuration (for the same OTP app)
      ip: "localhost",
      port: 20717

    config :my_app, my_app_databases: [Databases.RepoOne, Databases.RepoTwo]

Our database engine used by `:my_app` needs to know what databases exist, and what the database configurations are. The database engine can make a call to `get_env(:my_app, :my_app_databases)` to retrieve the list of databases (specified by module names). Our database engine can then traverse each repository in the list and then call `get_env(:my_app, Databases.RepoOne)` and so forth to retrieve the configuration of each one.

Link to this function

# load(app)

View Source

## Specs

    load(app()) :: :ok | {:error, term()}

Loads the given `app`.

In order to be loaded, an `.app` file must be in the load paths. All `:included_applications` will also be loaded.

Loading the application does not start it nor load its modules, but it does load its environment.

Link to this function

# loaded_applications()

View Source

## Specs

    loaded_applications() :: [{app(), description :: charlist(), vsn :: charlist()}]

Returns a list with information about the applications which have been loaded.

Link to this function

# put_all_env(config, opts \\ [])

View Source (since 1.9.0)

## Specs

    put_all_env([{app(), [{key(), value()}]}],
      timeout: timeout(),
      persistent: boolean()
    ) :: :ok

Puts the environment for multiple apps at the same time.

The given config should not:

- have the same application listed more than once
- have the same key inside the same application listed more than once

If those conditions are not met, the behaviour is undefined (on Erlang/OTP 21 and earlier) or will raise (on Erlang/OTP 22 and later).

It receives the same options as `put_env/4`. Returns `:ok`.

Link to this function

# put_env(app, key, value, opts \\ [])

View Source

## Specs

    put_env(app(), key(), value(), timeout: timeout(), persistent: boolean()) :: :ok

Puts the `value` in `key` for the given `app`.

## Options

- `:timeout` - the timeout for the change (defaults to `5_000` milliseconds)
- `:persistent` - persists the given value on application load and reloads

If `put_env/4` is called before the application is loaded, the application environment values specified in the `.app` file will override the ones previously set.

The `:persistent` option can be set to `true` when there is a need to guarantee parameters set with this function will not be overridden by the ones defined in the application resource file on load. This means persistent values will stick after the application is loaded and also on application reload.

Link to this function

# spec(app)

View Source

## Specs

    spec(app()) :: [{application_key(), value()}] | nil

Returns the spec for `app`.

The following keys are returned:

- `:description`
- `:id`
- `:vsn`
- `:modules`
- `:maxP`
- `:maxT`
- `:registered`
- `:included_applications`
- `:applications`
- `:mod`
- `:start_phases`

Note the environment is not returned as it can be accessed via `fetch_env/2`. Returns `nil` if the application is not loaded.

Link to this function

# spec(app, key)

View Source

## Specs

    spec(app(), application_key()) :: value() | nil

Returns the value for `key` in `app`'s specification.

See `spec/1` for the supported keys. If the given specification parameter does not exist, this function will raise. Returns `nil` if the application is not loaded.

Link to this function

# start(app, type \\ :temporary)

View Source

## Specs

    start(app(), restart_type()) :: :ok | {:error, term()}

Starts the given `app`.

If the `app` is not loaded, the application will first be loaded using `load/1`. Any included application, defined in the `:included_applications` key of the `.app` file will also be loaded, but they won't be started.

Furthermore, all applications listed in the `:applications` key must be explicitly started before this application is. If not, `{:error, {:not_started, app}}` is returned, where `app` is the name of the missing application.

In case you want to automatically load and start all of `app`'s dependencies, see `ensure_all_started/2`.

The `type` argument specifies the type of the application:

- `:permanent` - if `app` terminates, all other applications and the entire node are also terminated.

- `:transient` - if `app` terminates with `:normal` reason, it is reported but no other applications are terminated. If a transient application terminates abnormally, all other applications and the entire node are also terminated.

- `:temporary` - if `app` terminates, it is reported but no other applications are terminated (the default).

Note that it is always possible to stop an application explicitly by calling `stop/1`. Regardless of the type of the application, no other applications will be affected.

Note also that the `:transient` type is of little practical use, since when a supervision tree terminates, the reason is set to `:shutdown`, not `:normal`.

Link to this function

# started_applications(timeout \\ 5000)

View Source

## Specs

    started_applications(timeout()) :: [
      {app(), description :: charlist(), vsn :: charlist()}
    ]

Returns a list with information about the applications which are currently running.

Link to this function

# stop(app)

View Source

## Specs

    stop(app()) :: :ok | {:error, term()}

Stops the given `app`.

When stopped, the application is still loaded.

Link to this function

# unload(app)

View Source

## Specs

    unload(app()) :: :ok | {:error, term()}

Unloads the given `app`.

It will also unload all `:included_applications`. Note that the function does not purge the application modules.

# Link to this section Callbacks

Link to this callback

# config_change(changed, new, removed)

View Source (optional)

## Specs

    config_change(changed, new, removed) :: :ok
    when changed: keyword(), new: keyword(), removed: [atom()]

Callback invoked after code upgrade, if the application environment has changed.

`changed` is a keyword list of keys and their changed values in the application environment. `new` is a keyword list with all new keys and their values. `removed` is a list with all removed keys.

Link to this callback

# prep_stop(state)

View Source (optional)

## Specs

    prep_stop(state()) :: state()

Called before stopping the application.

This function is called before the top-level supervisor is terminated. It receives the state returned by `c:start/2`, if it did, or `[]` otherwise. The return value is later passed to `c:stop/1`.

Link to this callback

# start(start_type, start_args)

View Source

## Specs

    start(start_type(), start_args :: term()) ::
      {:ok, pid()} | {:ok, pid(), state()} | {:error, reason :: term()}

Called when an application is started.

This function is called when an application is started using `Application.start/2` (and functions on top of that, such as `Application.ensure_started/2`). This function should start the top-level process of the application (which should be the top supervisor of the application's supervision tree if the application follows the OTP design principles around supervision).

`start_type` defines how the application is started:

- `:normal` - used if the startup is a normal startup or if the application is distributed and is started on the current node because of a failover from another node and the application specification key `:start_phases` is `:undefined`.
- `{:takeover, node}` - used if the application is distributed and is started on the current node because of a failover on the node `node`.
- `{:failover, node}` - used if the application is distributed and is started on the current node because of a failover on node `node`, and the application specification key `:start_phases` is not `:undefined`.

`start_args` are the arguments passed to the application in the `:mod` specification key (for example, `mod: {MyApp, [:my_args]}`).

This function should either return `{:ok, pid}` or `{:ok, pid, state}` if startup is successful. `pid` should be the PID of the top supervisor. `state` can be an arbitrary term, and if omitted will default to `[]`; if the application is later stopped, `state` is passed to the `stop/1` callback (see the documentation for the `c:stop/1` callback for more information).

`use Application` provides no default implementation for the `start/2` callback.

Link to this callback

# start_phase(phase, start_type, phase_args)

View Source (optional)

## Specs

    start_phase(phase :: term(), start_type(), phase_args :: term()) ::
      :ok | {:error, reason :: term()}

Starts an application in synchronous phases.

This function is called after `start/2` finishes but before `Application.start/2` returns. It will be called once for every start phase defined in the application's (and any included applications') specification, in the order they are listed in.

Link to this callback

# stop(state)

View Source

## Specs

    stop(state()) :: term()

Called after an application has been stopped.

This function is called after an application has been stopped, i.e., after its supervision tree has been stopped. It should do the opposite of what the `c:start/2` callback did, and should perform any necessary cleanup. The return value of this callback is ignored.

`state` is the state returned by `c:start/2`, if it did, or `[]` otherwise. If the optional callback `c:prep_stop/1` is present, `state` is its return value instead.

`use Application` defines a default implementation of this function which does nothing and just returns `:ok`.