Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[erlang-server] Usage instructions for using erlang-server stubs missing #1281

Closed
ghost opened this issue Oct 21, 2018 · 5 comments
Closed

Comments

@ghost
Copy link

ghost commented Oct 21, 2018

Disclaimer: I was told by William Cheng to cross-post this here. This is not a real bug report, but probably a request for documentation or clarification.

Description

I am currently trying to develop a REST API using Erlang. I used OpenAPI (Swagger) to define the API and wanted to use their openapi-generator to create the stubs and some helper code. This also works and some code is generated, but I cannot find any documentation on what I have to do from there.

For the explanation of my problem, I will refer to their sample output from code generation for erlang-server.

I have two main problems at the moment:

  • I cannot find an entry point into the code (e.g. a init/0 or start/0 function)
  • I am not sure which function I have to implement to execute my code on each endpoint. I think that I have to implement handle_request, but the execution path seems a bit weird to me.
Which function to implement

In openapi_router they define openapi_pet_handler to be the handler for 'AddPet'. In that module, there is a function called handle_request_json, which tries to populate the request and in case of OK executes openapi_logic_handler:handle_request(LogicHandler, ...).

openapi_logic_handler:handle_request(Handler, ...) takes that handler and executes Handler:handle_request(OperationID, Req, Context).. This leads me to the conclusion, that I probably have to implement openapi_pet_handler:handle_request with my custom code.

How to start the server

I checked the code and it seems to use cowboy as a web server. At least it includes dependencies to cowboy in the generated openapi.app.src. However, in rebar.config there is no reference to cowboy.

In the cowboy tutorial, they use erlang.mk to build their project. This allows them to run the code with make run. With rebar this does not seem to be possible. I did not find a specific command for rebar to start a program. You seem to have to know the entrypoint (init function) if you use rebar.

However, I am not able to find any function that looks like it could be an init function in the generated stub code.

Summary

Can somebody explain what has to be done to use the stub generated by openapi-generator for erlang-server? Do I have to setup my own cowboy project and then somehow link the stubs into it? If yes, how?

Further Checks

I also did some further tests and research regarding the problem of starting the application, which I will explain in the section "Steps to reproduce". I will use your petstore erlang-server example for this, so that you can follow along and see whether I made any mistakes or not.

openapi-generator version

3.3.1: openapi-generator-cli-3.3.1.jar

OpenAPI declaration file content or url

Usually molescrape.yml, but to make it simpler for you I worked with openapi.yml (petstore).

Command line used for generation

For the example below, I directly used your generated code. That way it will be easier to follow along.

Steps to reproduce

So, first let's clone the repository:

git clone https://github.com/OpenAPITools/openapi-generator

We have the erlang-server code in openapi-generator/samples/server/petstore/erlang-server now. As far as I understand, this is an erlang application, with an openapi.app(.src) file. And it uses rebar for compilation. Thus, let's fetch the dependencies and compile the project.

rebar get-deps
rebar compile

Gives us a failure in jesse, which is easy to fix.

$HOME/openapi-generator/samples/server/petstore/erlang-server/deps/jesse/src/jesse_tests_util.erl:92: erlang:get_stacktrace/0: deprecated; use the new try/catch syntax for retrieving the stack backtrace
Compiling $HOME/openapi-generator/samples/server/petstore/erlang-server/deps/jesse/src/jesse_tests_util.erl failed

I just opened the file and fixed the deprecated code in line 92 to be newstyle stacktrace. rebar compile now works.

According to my research, an Erlang Application must have an entrypoint file with a start/2 and a stop/1 method. If I grep the source directory of this code, there is no start method:

grep -r "start" ./src/

Neither does the openapi.app file include the mod field that should link to the entrypoint module.

Thus, I am not sure if this is supposed to be an Erlang application or not (I am quite new to Erlang). I guess that it can be an application if I want it to be and the stub generator just wants to give me freedom in this decision?

So, I decide this should be an application so that I can run it as a web server. And it this point it got lost in confusion after my research. The Erlang help references to a supervisor behaviour module, which looks very similar in its return type as the ranch Embedded Mode, which in turn uses the ranch:child_spec that is also produced by openapi_server.erl.

Thus, I'd say let's implement an application module and a supervisor module.

% petstore_app.erl
-module(petstore_app).
-behaviour(application).
-export([start/2, stop/1]).

start(_Type, _Args) ->
    petstore_sup:start_link().

stop(_State) ->
    ok.
% petstore_sup.erl
-module(petstore_sup).
-behaviour(supervisor).

-export([start_link/0]).
-export([init/1]).

start_link() ->
    supervisor:start_link(petstore_sup, []).

init(_Args) ->
    RanchSupSpec = {ranch_sup, {ranch_sup, start_link, []},
		permanent, 5000, supervisor, [ranch_sup]},
    Opts = #{ip => {127, 0, 0, 1}, port => 8080, net_opts => []},
    % Not sure about the ID parameter
    ListenerSpec = openapi_server:child_spec(1, Opts),

    {ok, {{one_for_one, 10, 10}, [RanchSupSpec, ListenerSpec]}}.

And set the application module in openapi.app.src:

...
    {mod, {petstore_app, []}}
...

Compile everything with rebar compile. And try to start it. For this, I start erlang with erl -pa ebin deps/*/ebin and then execute there:

application:ensure_all_started(openapi).

This then gives me:

{error,{cowboy,{"no such file or directory","cowboy.app"}}}

Okay, I think we're lacking a dependency here, so let's add it. I changed rebar.config to include:

...
    {cowboy, {git, "https://github.com/ninenines/cowboy.git", {tag, "1.1.2"}}}
...

I chose version 1.1.2 here, because according to #1135, only Cowboy v1 is supported.

rebar get-deps
rebar compile
erl -pa ebin deps/*/ebin

And then again I try:

application:ensure_all_started(openapi).

Resulting in:

=SUPERVISOR REPORT==== 21-Oct-2018::11:43:49.551064 ===
    supervisor: {<0.118.0>,petstore_sup}
    errorContext: start_error
    reason: {already_started,<0.108.0>}
    offender: [{pid,undefined},
               {id,ranch_sup},
               {mfargs,{ranch_sup,start_link,[]}},
               {restart_type,permanent},
               {shutdown,5000},
               {child_type,supervisor}]
=CRASH REPORT==== 21-Oct-2018::11:43:49.552607 ===
  crasher:
    initial call: application_master:init/4
    pid: <0.116.0>
    registered_name: []
    exception exit: {{shutdown,
                         {failed_to_start_child,ranch_sup,
                             {already_started,<0.108.0>}}},
                     {petstore_app,start,[normal,[]]}}
      in function  application_master:init/4 (application_master.erl, line 138)
    ancestors: [<0.115.0>]
    message_queue_len: 1
    messages: [{'EXIT',<0.117.0>,normal}]
    links: [<0.115.0>,<0.42.0>]
    dictionary: []
    trap_exit: true
    status: running
    heap_size: 376
    stack_size: 27
    reductions: 210
  neighbours:
=INFO REPORT==== 21-Oct-2018::11:43:49.554098 ===
    application: openapi
    exited: {{shutdown,
                 {failed_to_start_child,ranch_sup,
                     {already_started,<0.108.0>}}},
             {petstore_app,start,[normal,[]]}}
    type: temporary

Seems that my supervisor now tries to start ranch multiple times or something like that.

I also tried starting all required modules one-by-one and then application:start(openapi)., this resulted in the same crash.

And here I am stuck now. I do not know how I have to start the server with the ranch:child_spec or if I am trying the right thing at all and there does not seem to be documentation on how to use the generated stubs.

Before I also reworked the code a bit so that it did not return the result of ranch:child_spec, but instead only the routing information for cowboy and then I started cowboy as given in their tutorial. I think that this brought me to a parsing error with jsx, which I then circumvented by commenting that part in the code. Then it started the server and crashed as soon as I tried to open a URL (unfortunately without any error). But I won't reproduce these steps here, because I think changing the stub code is not the intended way of using it.

If you've reached this point at reading, please don't forget that starting the application is only the first part of the problem. The second one is knowing in which functions I have to implement my custom code.

Related issues/PRs

None.

Suggest a fix/enhancement
  • Add comments to the generated code or into the README.md with instructions on usage and which functions have to be implemented with custom code.
  • Fix the dependency on cowboy in rebar.config (at least that also seems to be missing, but I might be wrong)
@ghost ghost changed the title Usage instructions for using erlang-server stubs missing [erlang-server] Usage instructions for using erlang-server stubs missing Oct 21, 2018
@wing328
Copy link
Member

wing328 commented Oct 26, 2018

cc @tsloughter @galaxie

@wing328
Copy link
Member

wing328 commented Oct 26, 2018

Fix the dependency on cowboy in rebar.config (at least that also seems to be missing, but I might be wrong)

FYI. There's an ongoing work to upgrade the code base to use Cowboy 2.x: #1305

@ghost
Copy link
Author

ghost commented Oct 28, 2018

@wing328 I think you selected the wrong tag. You selected Client: Erlang, but it should be Server: Erlang.

@feihongmeilian
Copy link
Contributor

feihongmeilian commented Nov 3, 2018

Hi @aufziehvogel

#1364 is an PR for upgrade 'erlang-server' from cowboy1.x to cowboy2.x. please help to code review, Thanks!

@wing328
Copy link
Member

wing328 commented Feb 25, 2019

@aufziehvogel let us know if you still need any help with the erlang-server generator.

@wing328 wing328 closed this as completed Feb 25, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants