I was working on umbrella project and wanted to add phoenix to app folder.
> cd umbrella_proj/apps ⮐
apps> mix phx.new.web app_web ⮐
....> Fetch and install dependencies? [Yn] Y ⮐
apps> cd app_web ⮐
app_web> iex -S mix phx.server ⮐
Till this point it should work normally. But
This what I got, and I think it should automatically add config :phoenix, :json_library, Jason to config/config.exs inside my app_web. So I had to add it manually.
Notice please in the "Compilation error" it throw ArgumentError and mentioned __Poison__ Module!! Not Jason 😕
warning: failed to load Jason for Phoenix JSON encoding
(module Jason is not available).
Ensure Jason exists in your deps in mix.exs,
and you have configured Phoenix to use it for JSON encoding by
verifying the following exists in your config/config.exs:
config :phoenix, :json_library, Jason
(phoenix) lib/phoenix.ex:40: Phoenix.start/2
(kernel) application_master.erl:277: :application_master.start_it_old/4
Compiling 11 files (.ex)
== Compilation error in file lib/auction_web/endpoint.ex ==
** (ArgumentError) invalid :json_decoder option. The module Poison is not loaded and could not be found
(plug) lib/plug/parsers/json.ex:54: Plug.Parsers.JSON.validate_decoder!/1
(plug) lib/plug/parsers/json.ex:32: Plug.Parsers.JSON.init/1
(plug) lib/plug/parsers.ex:245: anonymous fn/3 in Plug.Parsers.convert_parsers/2
(elixir) lib/enum.ex:1925: Enum."-reduce/3-lists^foldl/2-0-"/3
(plug) lib/plug/parsers.ex:228: Plug.Parsers.convert_parsers/2
(plug) lib/plug/parsers.ex:224: Plug.Parsers.init/1
(plug) lib/plug/builder.ex:302: Plug.Builder.init_module_plug/4
(plug) lib/plug/builder.ex:286: anonymous fn/5 in Plug.Builder.compile/3
After modifying config/config.exs it worked normally.
This what I got, and I think it should automatically add config :phoenix, :json_library, Jason to config/config.exs inside my app_web
Since all umbrella child apps share configuration, as of recent Elixir & Phoenix versions it's recommended to put shared configuration in umbrella root config/config.exs. Dependency configuration, like this for config :phoenix, json_library: is considered shared. See: https://github.com/phoenixframework/phoenix/blob/v1.4.0/installer/templates/phx_umbrella/config/config.exs#L5:L12
It might be tricky to adjust mix phx.new.web generator to adjust umbrella root config.
Btw, Jason will be the default in Phoenix v2.0.
Ya, but in the main config.exs file of my umbrella project, it was not configured for any :json_library and also inside the phx app itself also was not configured. That's why it throw this error. I'd prefer mix phx.new.web to set its configuration in its own config.exs file. So for whatever reason I had to remove the phx app it will not leave hanging configurations in the main config.exs file of umbrella.
About Jason will be default in Phoenix v2.0, that's why I wonder when I saw in the ArgumentError throw invalid :json_decoder option and tells about _Poison_ not _Jason_.
I also find this a bit confusing. I understand wanting the configuration to be in the top level config.exs of the umbrella if you create that umbrella through Phoenix. But I also have an umbrella application that existed before I decided to bring in Phoenix and this error threw me for a loop. I don't think the generator should modify the umbrella config.exs but it _should_ know for itself that it needs Jason as its json_library.
I understand wanting the configuration to be in the top level config.exs of the umbrella if you create that umbrella through Phoenix.
FWIW this advice applies to non-Phoenix umbrella projects going forward as well: https://github.com/elixir-lang/elixir/pull/8195/files
I mentioned yesterday that it might be tricky for generator to adjust the config, I guess what I was really thinking is we shouldn't do it :) So the only thing left seems to improve the error message? What would be a better error message?
@geolessel
Actually I had this issue while reading your book __Phoenix in Action__. Although I follow exactly how you added phoenix app to umbrella app, but I got this issue .. it seems it was not exist in version of phoenix you were using. Waiting for final release of your book. 🤓
@wojtekmach Actually error message was so clear for me and didn't take me a second to figure out what to do to solve it. And if it is tricky to adjust the main config file of umbrella, why not adjust the config file of the phoenix app itself. The json_library is used by phoenix only I think so it meant to be in phoenix's config file only.
The json_library is used by phoenix only I think so it meant to be in phoenix's config file only.
@alaadahmed that would go against the advice given by Elixir & Phoenix which I linked to. In other words, it's recommended that we only do config :my_app, ... in apps/my_app/config/*, otherwise it goes to umbrella root.
Imagine you have two Phoenix apps in your umbrella, where do you put config :phoenix, json_library: ...? In one or the other Phoenix app? In both? Since the configuration is shared the only sensible option is to put it at the root.
While one could configure all applications here, we prefer to keep the configuration of each individual child application in their own app, but all other dependencies, regardless if they belong to one or multiple apps, should be configured in the umbrella to avoid confusion.
This is from the Elixir commit you linked, @wojtekmach, and I must admit I find it a bit confusing. It seems to be contradicting. However, I think I have figured out the difference in thinking between the two arguments:
config directory inside the umbrella.Imagine you have two Phoenix apps in your umbrella, where do you put config :phoenix, json_library: ...? In one or the other Phoenix app? In both? Since the configuration is shared the only sensible option is to put it at the root.
This is a good thought experiment @wojtekmach. But what if I have a legacy Phoenix app that wants/needs to use one json library and I have a new one that wants/needs to use Jason—both in the same umbrella. How would that work? Could we not have a way in which our app's version of Phoenix is configured differently than the dependency on a global level?
Actually I had this issue while reading your book Phoenix in Action.
@alaadahmed Haha, that's funny. I'm going through and running all the code listings myself before it goes into final production and came across this last night. Indeed, the first half of the book was written geared towards Phoenix 1.3 so everything needs to be updated.
This is from the Elixir commit you linked, @wojtekmach, and I must admit I find it a bit confusing. It seems to be contradicting.
I'm sure the wording can be improved, I just don't know how exactly at the moment! Just to make sure we're on the same page, the idea was that obviously people can do whatever they want and put configuration whenever, however we nudge them to configure app _itself_ in _it's_ config/*.exs configuration but it's dependencies (be it Hex libraries configs, :logger config etc) in umbrella root.
But what if I have a legacy Phoenix app that wants/needs to use one json library and I have a new one that wants/needs to use Jason—both in the same umbrella. How would that work?
We cannot make this work at the moment. That's a known caveat of using application env to configure libraries, if we'd configure it instead as e.g. config :my_app, :phoenix_json_library: ... it would be possible. That being said, even if we have a legacy Phoenix app and a brand new Phoenix app in the same umbrella, they're always using the same Phoenix version anyway, so I'd say do whatever is most appropriate for that given Phoenix version.
The behavior is expected, but I can see how the error can be confusing. Poison remains the default JSON library for backwards compatible reasons. On startup, we warn if we are unable to find a configured JSON library, telling you how to add it (the Jason warning and instructions), however, since Poison is the default, we will still use it, which leads to the error you are experiencing. Note that phx.new --umbrella based applications include the JSON library config so this shouldn't be an issue for most users. I am hesitant to add extra steps to the phx.new.web instructions about verifying the root config/config.exs contains the json config, since it won't be relevant to most users.
@alaadahmed do you have any thoughts on making the warning better? Since the warning instructions were enough for you to continue, I don't consider this an issue. If you have ideas on making it clearer, please let us know. Thanks!
@chrismccord 👍 Thanks for chiming in and for the explanation.
@chrismccord Imo one way to make the warning clearer is to mention the fact that, if you are within an umbrella project, the configs should go in the umbrella project folder, as opposed to the Phoenix app folder.
I ran into this issue when I did mix phx.new my_app inside the apps folder of a non-Phoenix umbrella project. I figured out what I had to do only after finding and reading this issue thread a few times, and even then what I did was a mix phx.new test --umbrella to see where the generated config files landed.
At that point, in my own project what I did was replace the umbrella config/ folder with my apps/my_app/config folder and then my mix ecto.create command worked like a charm.
Most helpful comment
@chrismccord Imo one way to make the warning clearer is to mention the fact that, if you are within an umbrella project, the configs should go in the umbrella project folder, as opposed to the Phoenix app folder.
I ran into this issue when I did
mix phx.new my_appinside theappsfolder of a non-Phoenix umbrella project. I figured out what I had to do only after finding and reading this issue thread a few times, and even then what I did was amix phx.new test --umbrellato see where the generated config files landed.At that point, in my own project what I did was replace the umbrella
config/folder with myapps/my_app/configfolder and then mymix ecto.createcommand worked like a charm.