2

I'm building a system that needs to use a previously built OTP application (lets call it X). If I want to build a new OTP application / module, how can I use the application that already exists from a module, for instance?

I assumed I could call start, since it follows the application behaviour, and so I built a minimalistic application Y that has the following code:

y.erl:

-module(y).
-behaviour(application).

start(_StartType, _StartArgs) ->
  io:format("going to call x_app~n"),
  {ok, _} = x_app:start([]),
  io:format("called x_app~n"),
  y:start_link().

stop(_State) ->
  ok = x_app:stop([]),
  ok.

Rebar compiles this code successfully and generates no warnings.
rel/y/bin/y start outputs nothing at all (I hoped to get the output of at least one io:format) rel/y/bin/y stop outputs Node is not running!

goncalotomas
  • 1,000
  • 1
  • 12
  • 29

1 Answers1

3

You need to list application x as a dependent application in your application's .app resource file, or since you're using rebar, in your .app.src file:

{application, your_app,
 [{description,"your application"},
  {vsn, "0.1"},
  {modules,[]},
  {registered, []},
  {mod,{your_app,[]}},
  {env, []},
  {applications,[kernel, stdlib, x]}]}.

Note in the very last line that x is listed as an application dependency. This results in the Erlang application controller ensuring that x is started before it starts your application. And if you're starting your application interactively in an Erlang shell via application:ensure_all_started/1,2 this declaration will ensure that x is started first before your app starts.

Steve Vinoski
  • 19,847
  • 3
  • 31
  • 46
  • Thank you very much for your answer. So that would imply that if I use `application:start(y).` after proper configuration of `x.app.src` I would see the expected results? I should probably drop the `x_app:start([]).` lines? – goncalotomas Mar 27 '16 at 21:48
  • 1
    Correct, you should not be starting the app from your own code as you've shown. If `y` depends on `x`, list `x` in `y.app.src` as I've shown and the normal Erlang release startup machinery will ensure they're started in the correct order. – Steve Vinoski Mar 27 '16 at 21:51
  • What about stopping the application? Does calling `application:stop(y).` terminate `x` as well? – goncalotomas Mar 27 '16 at 21:54
  • Another question - where must `x` reside at the time of running `rebar generate`? I listed `x` as a dependency and thus it is saved to my `deps/` directory, but running `rebar generate` outputs `Release \"y\" uses non existing application x`. – goncalotomas Mar 27 '16 at 22:06
  • 1
    Running `application:stop(y)` stops only application `y`. But if you're running a release, shutting down the node will stop all apps in reverse of their start order. As for the `rebar generate` error, maybe this question will help: http://stackoverflow.com/q/10476790/409228 – Steve Vinoski Mar 27 '16 at 23:07
  • Would you mind pointing me to instructions as to how I should setup my `reltool.config` file? The question you linked seems specific and contains a sample `relltool.config` that has many lines I don't understand. – goncalotomas Mar 27 '16 at 23:12
  • 1
    There's the rebar wiki: https://github.com/rebar/rebar/wiki/Release-handling , see also this question: http://stackoverflow.com/q/17482732/409228 , and you might also consider switching to [rebar3](https://www.rebar3.org) since it handles releases a lot better than `rebar`. – Steve Vinoski Mar 27 '16 at 23:16
  • Thank you again for all your help! – goncalotomas Mar 27 '16 at 23:17