Up until very recently, adding Nitrogen to an existing application was an exercise in frustration, even for Erlang veterans. This is no longer the case, adding Nitrogen to an existing application is now a snap with the new embed
helper script.
Originally, If you were starting from scratch and making a Nitrogen-focused app, it was simple, just run make rel_XXX
or make slim_XXX
) (where XXX is the backend of choice). But if you had an already existing application and you wanted to add a web front-end or web interface and use Nitrogen, then you had to follow a bunch of steps, copying files from one repository, changing paths in files, adding dependencies - in short, it was a pain.
embed
The new embed
script was just added to the root of what will soon be Nitrogen 2.2.0.
This script will do all the heavy lifting for you, asking your preferences, automatically merging dependencies, adding Makefile rules, and copying the necessary files for the backend of your choice.
With this script, the only manual changes you'll have to are to your launch script: Add the necessary code paths, config file loading, and either making the call to nitrogen_sup:start_link()
, or simply including that into your supervisor tree.
/path/to/nitrogen/embed
-pa deps/nitrogen_core/ebin
, -config path/to/file.config
for each config file, and a call to -eval "nitrogen_sup:start_link()"
(or add it to your supervision tree)make
(if your makefile does everything necessary), or rebar get-deps
followed by rebar compile
.Navigate browser to http://127.0.0.1:8000
For a simple demonstration, let's do something completely contrived. Let's add a web interface to qdate, the date and timezone utility.
First, we clone qdate and Nitrogen.
$ git clone git://github.com/choptastic/qdate.git $ git clone git://github.com/nitrogen/nitrogen.git
Now we enter the qdate directory, and to be safe, let's make a 'web-interface' branch
cd qdate $ git checkout -b web-interface
Now we make the call to embed
. Currently, we must make sure to make the call from the directory we wish to install to. So we call it like this (I'm just including the pwd
call to demonstrate our current location).
$ pwd /home/user/qdate $ ../nitrogen/embed
Which will result in you seeing this:
************************************************************** **** NITROGEN WEB FRAMEWORK EMBEDDER **** **** **** **** Adding Nitrogen to an existing Erlang Application **** **** **** ************************************************************** NOTE: BEFORE PROCEEDING IT'S HIGHLY RECOMMENDED THAT YOU MAKE NEW BRANCH IN YOUR SOURCE CODE MANAGEMENT SYSTEM, OR AT LEAST MAKE A BACKUP OF YOUR DIRECTORY, AS THIS WILL MAKE CHANGES TO THE CURRENT DIRECTORY TREE BY ADDING AND MODIFYING FILES. Will be installing from '/home/user/nitrogen' into '/home/user/qdate' Web server to use? Options are (c)owboy, (i)nets, (m)ochiweb, (w)ebmachine, (y)aws. Please choose (i/m/c/w/y):
Here you enter your choice: c, i, m, w, or y
For our demonstrating we'll choose cowboy, so we type c
and press enter
Now we are presented with a series of path questions, with sensible defaults provided. Pressing "Enter" will stick with the default, or you can type the updated path (paths will be relative to the current working directory).
Where to put the Erlang code for Nitrogen pages and initialization [Default: src/nitrogen/]: Where to put the Erlang headers [Default: include/]: Where to put the static directory (for js, css, etc) [Default: priv/static/]: Where to put the templates directory [Default: priv/templates/]: Where to put the config files [Default: etc/]:
After the paths are provided, you're presented with a series of yes/no questions:
Install the plugin scripts and configs? (y/n): y Add Nitrogen dependencies to rebar.config automatically? (nitrogen_core, simple_bridge, nprocreg, sync, cowboy, and any of cowboy's dependencies. (y/n): y Add a 'make plugins' rule to the Makefile? (y/n): y Add a 'make copy-static' rule to the Makefile? (y/n): y Run 'make' after installation? (y/n): y
Note: Unless you want to do something manually, it's recommended to choose "y" for all provided questions.
Finally, we get down to it. The embed script presents us with our chosen preferences, and a final "Are you sure you want to proceed?" question.
************************************************ *** We're almost ready to go. Please review: *** Erlang Source: src/nitrogen/ *** Erlang Headers: include/ *** Static Resources: priv/static/ *** Nitrogen Templates: priv/templates/ *** Config Files: etc/ *** Install Plugin Script: Yes *** Add 'make plugins' rule to Makefile: Yes *** Add 'make copy-static' rule to Makefile: Yes *** Add dependencies to rebar.config: Yes *** Run 'make' after all is complete: Yes ************************************************ Are you sure you want to proceed? (y/n):
Entering y
and pressing Enter will begin the installation process.
After fast-scrolling informative text (telling you what the script is doing, followed, if you specified it, by the running of make
), you'll be presented with the following summary with some instructions:
******************************************************************************* **** Installation Complete **** ******************************************************************************* There are a few manual steps you must take before you're completely set up: 1) You must make sure to start Nitrogen. The easiest way is by adding `nitrogen_sup:start_link()` to your application. 2) You must make sure that the config files in etc/ are properly loaded. This can be done with a vm.args file if you're using a reltool generated release, or it can be done by adding additional -config calls to the commandline call that launches your app. 3) You may need to add the new packages (nitrogen_core, simple_bridge, nprocreg, etc) to your app's code path (the easy way is with the -pa flag in the `erl` call.) Congratulations on adding Nitrogen to your Application
As it says, we're almost there. Now we just need to make some changes to the launch script:
Let's edit Makefile and make a change. Currently, make run
is the quick way to launch a qdate
terminal, so let's edit that run
rule in the Makefile.
Original:
run: erl -pa ebin/ deps/*/ebin/ -eval "application:start(qdate)"
Let's load some configs, and add a call to start nitrogen:
run: erl -pa ebin/ deps/*/ebin/ -config etc/cowboy.config -config etc/app.config -eval "application:start(qdate)" -eval "nitrogen_sup:start_link()"
(Note: we didn't need to modify the path, since -pa deps/*/ebin
was already in there, which covers all necessary dependency paths for us.)
Finally, let's launch qdate
and see if we get the default Nitrogen page:
$ make run erl -pa ebin/ deps/*/ebin/ -config etc/cowboy.config -config etc/app.config -eval "application:start(qdate)" -eval "nitrogen_sup:start_link()" Erlang R16B (erts-5.10.1) [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false] Eshell V5.10.1 (abort with ^G) 1> Starting Cowboy Server (nitrogen) on 0.0.0.0:8000, root: './priv/static'
Perfect! Let's see what happens when we navigate our browser to http://127.0.0.1:8000
Great! It's also loading the default "Welcome to Nitrogen" page.
The last step is to simply add a web interface for qdate
.
So let's delete the unnecessary 'mobile.erl' pages from src/nitrogen
(our sensible default) and we'll just make a simple change to index.erl.
cd src/nitrogen rm index.erl
Let's change it to this:
-module (index). -compile(export_all). -include_lib("nitrogen_core/include/wf.hrl"). main() -> #template { file="./priv/templates/bare.html" }. title() -> "Welcome to qdate". body() -> #container_12 { body=[ #grid_8 { alpha=true, prefix=2, suffix=2, omega=true, body=inner_body() } ]}. inner_body() -> [ #h1 { text="Welcome to qdate" }, #label{text="Enter a free-form date and time here"}, #textbox{id=source_date, text=qdate:to_string("l, F jS, Y g:i A T")}, #label{text="Enter a new format string"}, #textbox{id=format_string, text="Y-m-d g:ia"}, #label{text="Enter a timezone to convert to"}, #textbox{id=timezone, text="America/Chicago"}, #br{}, #button{text="Convert", postback=convert}, #panel{text="", id=result} ]. event(convert) -> [From, String, TZ] = wf:mq([source_date, format_string, timezone]), wf:update(result, qdate:to_string(String, TZ, From)).
And recompile (we can enabled sync, if you so desire, or just kill the server and run make
). After compiling and loading the modules, we get this:
We can enter a source date, a new format, and a timezone, and it'll do the conversion for us using qdate
.
While this example is pretty contrived, it gives us an idea of just how much easier it is to add Nitrogen to an application now without having to jump through a bunch of hoops, or a series of tubes, if you will.