Running Erlang code and projects in Yaws (ebin_dir) - erlang

I'm exploring Yaws and I've read the Yaws manual and the Building Web Applications with Erlang book. I've followed every step in the book's last chapter where a multi_cast app is built, but I can't run it. I believe it's the Erlang code which isn't being found or used.
I've got a project dir in my home directory and I've pointed Yaws docroot for this particular Virtual Server to my project directory where a htdocs dir with the .yaws files reside.
<server localhost>
port = 8001
listen = 127.0.0.1
docroot = <my_path_here>/erlang_yaws/multi_cast
</server>
and I've changed the ebin_dir to also point to the project´s ebin directory:
ebin_dir = <my_path_here>/erlang_yaws/multi_cast/_build/default/lib/multi_cast/ebin
Upon starting Yaws with yaws -i I can go to some simple .yaws files I've got which do not rely on any of the project´s .beam files. However, when I change my browser's location to a .yaws files which rely on the app's compiled files I get the following error:
=ERROR REPORT==== 21-Jan-2017::14:27:17 ===
ERROR erlang code threw an uncaught exception:
File: <my_path_here>/erlang_yaws/multi_cast/htdocs/status.yaws:1
Class: exit
Exception: {noproc,{gen_server,call,[multi_cast_front,{get_etag}]}}
Req: {http_request,'GET',{abs_path,"/htdocs/status.yaws"},{1,1}}
Stack: [{gen_server,call,2,[{file,"gen_server.erl"},{line,204}]},
{m_27449121_1,out,1,
[{file,"<my_path_here>/.yaws/yaws/default/m_27449121_1.erl"},
{line,35}]},
{yaws_server,deliver_dyn_part,8,
[{file,"yaws_server.erl"},{line,2872}]},
{yaws_server,aloop,4,[{file,"yaws_server.erl"},{line,1242}]},
{yaws_server,acceptor0,2,[{file,"yaws_server.erl"},{line,1065}]},
{proc_lib,init_p_do_apply,3,[{file,"proc_lib.erl"},{line,247}]}]
I believe this is due to the fact that my gen_server app isn't starting correctly or not being found? The source code seems to compile successfully.
I'm on MacOS Sierra with Yaws 2.0.4, Erlang 19 and I did a regular Yaws install with homebrew.
Also, is there a resource which thoroughly explains how to structure Yaws and a simple application? Reading both the manual and the book and both fail at explaining this (or I'm really thick), and it's quite frustrating to get stuck from a user experience viewpoint.

You've correctly added your modules to the load path using the ebin_dir configuration variable, but that's not enough to actually start and run your application. The book you're following doesn't address this — see page 101, where it says, "It is also possible to run Yaws as an OTP app inside an existing Erlang setup, but this is beyond the scope of this book."
An easy way to start your server is to use the runmod configuration variable, documented in the yaws_config man page:
runmod = ModuleName At startup Yaws will invoke ModuleName:start() in a separate process. It is possible to have several runmods. This is useful if we want to reuse the Yaws startup shell script for our own application.
Assuming your gen_server provides a start/0 function, set the name of your module as the value of runmod and Yaws will start it. A problem with this approach, though, is that it works fine for experimentation but not for production because there's nothing supervising your gen_server.
A better approach is to have a full OTP application running alongside Yaws. With this approach, your application's supervisors manage your workers. One way to do this is by using yapps (Yaws applications). Another way is to create a release containing both Yaws and your application. Still another way is to let Yaws supervise your workers.
Addressing the second part of your question requires defining what you mean by "a simple application". Is it a simple static page application? A simple application using .yaws pages? A simple SSE application? A simple appmod application? A simple websocket application? A simple application running as a sibling of Yaws? There are a variety of possible definitions. The best short answer is to always structure your application using OTP design principles. You might also consider sending questions on this topic to the Yaws mailing list.

Related

getting process ID of a pub serve to then kill that thread/process

So when I run my Polymer Dart application, i use pub serve and the serve is created and served. It will stay running until until i break out of it. I was curious if there is a way to programmatically stop it.
One of the options I was looking at was looking at the running processes and then killing the pub serve process.
I was not sure though how i would get the process id to kill it, or unless there was another option.
Maybe someone has an even better approach to shutdown pub serve on the machine automatically, as a form of cleanup?
The issue I have noticed is that if i get the running proceesses, i only see "cmd" as a process so that isnt the best determining factor.
I was not sure if there was a way via pub on serve to get its process if, if it set a flag or global of sorts I could leverage
This is not a Dart or Pub question really, it's a Windows, MacOS, Linux etc. shell process control question.
The question is more suited to Stack Exchange Superuser https://superuser.com/ I believe. You could look over there for more detailed answer ... but ... assuming you are using the windows command prompt:
start /B starts a process in the background.
tasklist can be used to look up running process PIDs.
taskkill /PID kills a running process.
You can use help <command> or search for documentation.
I have not used these personally but it looks awkward as start /B does not give you the PID of the process it ran. Unix shells such as Bash have good facilities for running processes in the background. Windows Powershell may have better support also.

Changes in YAWS takes a while to take effect

When I modify a .yaws file it take a few (5, 10) seconds for changes to take effect, it it normal and Do I have to keep terminal open while I use YAWS server?
When you modify a .yaws file, Yaws recompiles it to an Erlang .beam file, which contains bytecode for the Erlang virtual machine, and reloads it. This won't be instantaneous of course, but it should not take 5-10 seconds; you should report a Yaws issue in that case, and please include a test case.
As for requiring a terminal, Yaws can run such that it gives you an interactive Erlang shell, or it can be run as a background daemon if you supply the --daemon command-line option. Yaws comes with a number of startup scripts for running it as a daemon on various operating systems.

Industry standard for running daemonized Erlang/OTP applications?

Some of modern infrastructure components such as Yaws and CouchDB can be installed on Ubuntu with
sudo apt-get install
and then they can be started with
{service_name} start or simply {service_name}
I wonder if there are any differences between this approach and the Erlang/OTP way, that is uploading an OTP release to the production server and then starting it with a rebar-generated script.
What is the industry standard? Install/start a repository-based binary or upload/start a rebar-generated release?
Also, do the repository-based binaries have all the OTP functionality in place, like OTP applications structure, supervision and the option to attach to the live application via console?
Every time, you are starting erlang, you are starting a release. Even, if you only type erl in terminal, it runs a release (you can find the .boot, .rel and .script files in erlang_rootdir/releases/name_of_release.
I think this answers your last question: packages installed from repository still have the OTP structure, supervision and all the goodies. There are just couple of bash scripts, that make starting and stopping them more friendly to someone used to service_name start. You should also be able to find a script similar to the one generated by rebar.
Check, where are those files and simply cat them. You should see, they simply start Erlang release.
The only thing, that you can't do with package managers, is hot code upgrade. Most package managers simply stop the running application, install new version and start it back. In Erlang, you can upgrade running release, but this is quite advanced stuff. Besides that - there are no disadvantages of using OS packages.

Benefit to the ".app" file in Erlang?

I've never really used the .app files for my projects. I understand those are required for loading an application through the application module.
Is there another use of such files?
The *.app along with the *.rel file is used to generate boot scripts. A boot script is used to automatically launch my application when erlang is started up. An application resource file describes what applications need to be running before my application can be launched. For instance, if I use mnesia and indicate that in the .app file for my application, when I generate a boot script and use it to start my application it will start mnesia for me when starting my own application.
While you may get automatic dependency installation/handling with other package managers the boot script is useful for managing dependencies in the startup of your application which is important in an OTP application setup.
note: applications in otp refers to a bundle of running processes and/or code. applications can depend on other applications in a number of ways. Either they require the code to be installed or they require the application to be running.
They're used for when building releases (with *.rel to generate boot scripts). I recommend just starting with the *.app file and the application behaviour callback though. As for starting with OTP. It is a nice sweet spot in development to do:
-module(foo).
-export([start/0]).
start() ->
[application:start(A) || A <- [sasl, inets, x, y, etc]].
to start all the applications you depend on having running for your application with a simple
$ erl -s foo
If your project is to be used as a service or framework to other projects, another benefit is that those Erlang applications can in turn depend on, or include, your application. An Erlang application is the unit in which to provide services and even libraries (stdlib is a library, no "moving parts", just library modules).
Being an Erlang application gives you a simple way to pass configuration parameters to your application. When you pass -mnesia dir '"/some/path"' to erl, it is accessed by the mnesia application as application:get_env(mnesia, dir). If you define an application called foo, you can pass -foo key 'some-Erlang-literal' to erl. The *.app file can contain defaults in the env section, the *.rel file overrides them, and the command line overrides that.
The *.app file has sections where you list the modules and registered processes your application introduces. This is used when building releases to check that there are no collisions between applications.
Some additional features of Erlang applications that I don't know well:
Start phases. Used for applications that have complex start-up needs, such as being "partially running" for a while.
Distributed applications. Used to define where the application should run in a cluster.
Takeover. Used to release a machine from the distributed application, such as if it needs maintenance or upgrading.
Eventually you will begin to want to start your application set in a more structured way, and that is when the whole release / boot-script is going to become more understandable. Or the opposite, you will think it is overkill for you specific needs. Just start with a simple *.app and a module with the application behaviour callbacks. You wont look back.

Is there a simpler way to deploy to WebSphere?

I have seen this question about deploying to WebSphere using the WAS ant tasks.
Is there a simpler way to do this? In the past I have deployed to Tomcat by dropping a war file into a directory. I was hoping there would be a similar mechanism for WebSphere that doesn't involve calling the IBM libraries or rely on RAD to be installed on your workstation.
Just a hint: if you activate "Log command assistance commands" in System Administration / Console preferences, you will get a logfile in the server log directory that contains the jython scripts for all actions you did on the console. So you can just deploy your stuff per console the first time, and then grab the commands for later and feed them into wsadmin.bat -lang jython "thecommandscomehere" for the next deployment.
There is the concept of WebSphere Rapid Deployment. It's supposed to be the same experience as what you describe for Tomcat.
One way to do it could be using Jython or jacl scripts. See those samples at IBM site.
[EDIT] Especially the wsadminlib.py.zip download near the bottom of the page contains a huge set of examples and helper functions to get you started.
WAS does provide a client jar containing some custom ant tasks. However they seem to be extremely bugy and dont work with remote servers.
IBM ANT TASK Javadoc
Netbeans also has support for was 6 and 6.1 but this again is still quite buggy, however it can be useful for generating some the bindings files etc.

Resources