Building Block View¶
To understand where the proposed MDD approach has its importance, the components involved in the Unix Web Socket communication have to be presented. Fig. 2 presents these components.
Since the AGL Application Framework and its API are already given in the AGL architecture, the rationale behind the design was to wrap the AGL Application Framework API and the Web Socket communication in an RPC-like approach. Moreover, the components were encapsulated applying functional decomposition. Table 3 shows the responsibilities for each of the components in Fig. 2.
Name | Responsibility |
---|---|
AGL Application Framework | Manage all AGL Services and their life cycle, Create Unix Web Socket for the RESTfull API to be served by the AGL Services, Forward RESTfull API verb calls to AGL Services verbs callbacks, Verbs authentication process handling. |
AGL Service | Initialize service resources, serve the RESTfull API, Forward the RESTfull API verbs to the corresponding Service Class method, Unmarshal JSON messages as to parse corresponding Service Class method parameters, Marshal output parameters of Service Class as JSON to reply through Unix Web Socket. |
Service Class | Implements the intended functionality at service side for each RESTfull API verb. |
Application | Use functionality exposed by the AGL Services to achieve a user-visible purpose. |
APP Class | Exposes all RESTfull API verbs as methods with input and output parameters, Marshal parameters as JSON to send requests to the Unix Web Socket, Unmarshal JSON replies to update output parameters. |
WebSocketApi | Handle Unix Web Socket connection, Form RESTfull API request, Wait for RESTfull API replies. |
raml2agl
features an automatic code generation tool developed.
Fig. 3 shows the building blocks of the tool and its
relations with the possible outputs.
As shown in Fig. 3, raml2agl
generates code for the
Service Class, App Class, and the AGL Service; the last two are fully
generated. Note that the automatically generated components are the ones with
more responsibilities, as shown in Table 3. This fact was
also the rationale behind the definition of the components, to automate most of
the process and reduce the overhead of creating a new Service and/or
Application. Moreover, Table 4 shows the
responsibilities of each of the raml2agl
components.
Name | Responsibility |
---|---|
RAML Parser | Read the RAML model and create a JSON model to be pass to the Jinja2 templates. |
Jinja2 Environment | Manage the templates, render the templates using the JSON model. |
raml2agl main | Read the RAML model from a file, Control the entire generation flow, reads input command line parameters, Calls the RAML Parser to generate JSON model, Calls the Jinja2 Environment to render the corresponding templates. |
Service Class¶
Fig. 4 shows an example of the output of
raml2agl
using the following model;
#%RAML 1.0
title: Example
mediaType: application/json
version: v1
baseUri: localhost:8000/api?token=x
/method_1:
post:
body:
properties:
param_in_1:
type: integer
get:
responses:
200:
body:
properties:
param_out_1:
type: integer
/method_2:
post:
body:
properties:
param_in_1:
type: string
get:
responses:
200:
body:
properties:
param_out_1:
type: string
Note that Service Class isn’t fully automatic generated. Nevertheless, a
skeleton of the entire class with all the methods definition is generated. Is
the task of the Service developer to finish the implementation of the
functionality. Moreover, each method represents a verb of the RESTfull API.
Hence, /example/method_1
will shall be implemented in
ServiceExample.method_1(...)
. Furthermore, the model title is the parsed
to name the RESTfull API and both classes.
WebSocketApi¶
Fig. 5 class diagram shows the definition of the
WebSocketApi
class.
Moreover, below the description of each of the classes members.
-
class
WebSocketApi
¶ Handle Unix Web Socket connection and transmission
Public Functions
-
WebSocketApi
(const char *uri, const char *api_name)¶ Constructor
Creates Unix Web Socket connection and initialize the wait loop
- Parameters
uri
: Base uri to the web socketapi_name
: API name
-
~WebSocketApi
()¶ Destructor
Releases the resources and disconnect from the Unix Web Socket
Protected Functions
-
json_object *
emit
(const char *verb, const char *object)¶ Send string to the specified API’s verb
- Return
- Reply JSON object
- Parameters
verb
: API’s verbobject
: Marshaled JSON object
Protected Attributes
-
bool
connected
¶ Flags connection status
Private Static Functions
-
static void
dec_callcount
()¶ Decrement the reference count of calls
-
static void
on_wsj1_hangup
(void *closure, struct afb_wsj1 *wsj1)¶ Hang up callback
- Parameters
closure
: Hangup’s closurewsj1
: Connection object
-
static void
on_wsj1_call
(void *closure, const char *api, const char *verb, struct afb_wsj1_msg *msg)¶ Receives a method invocation callback
- Parameters
closure
: Call’s closureapi
: API Nameverb
: API’s verbmsg
: Message to be sent
-
static void
on_wsj1_event
(void *closure, const char *event, struct afb_wsj1_msg *msg)¶ Receive an event callback
- Parameters
closure
: Event’s closureevent
: Issued eventmsg
: Received message
-
static void
on_wsj1_reply
(void *closure, struct afb_wsj1_msg *msg)¶ Receive a reply callback
- Parameters
closure
: Reply’s closuremsg
: Replied message
-
static int
wsj1_call
(const char *api, const char *verb, const char *object)¶ Send a marshaled object to the specified API and API’s verb
- Return
- Return POSIX error codes
- Parameters
api
: API nameverb
: API’s verbobject
: Marshalled JSON object
Private Static Attributes
-
struct afb_wsj1_itf
wsj1_itf
¶ The Web Socket callback interface for wsj1
-
struct afb_wsj1 *
wsj1
¶ The Web Socket connection object
-
int
exonrep
¶ The Web Socket connection object
-
int
callcount
¶ Calls Reference counter
-
sd_event *
loop
¶ Wait loop event
-
bool
reply
¶ Flags the presens of a reply
-
json_object *
curr_reply
¶ Last received JSON object
-
APP Class¶
As shown in Fig. 4 the Example
APP Class
has symmetric methods with ServiceExample
. Therefore, a call to
Example.method_1
will call /example/method_1
RESTfull API
through the Unix Web Socket. Note that every APP Class is completely
automatically generated. Moreover, APP Class inherits WebSocketApi
and implements the entire Unix Web Socket communication its methods.
AGL Service¶
An AGL service is basically the implementation of the Application Framework API shown in Fig. 6.
Furthermore, to implement Fig. 4, for instance, a null-terminated list of verbs has to be defined as follows;
static const struct afb_verb_v2 verbs[] = {
/*Without security*/
{.verb = "method_1", .callback = method_1, .auth = NULL, .info = "method_1", .session = 0},
{.verb = "method_2", .callback = method_2, .auth = NULL, .info = "method_2", .session = 0},
{.verb = NULL, .callback = NULL, .auth = NULL, .info = NULL, .session = 0 }
};
Note that for an initial implementation the authentication mechanisms weren’t
implemented. Nevertheless, it has been included in the raml2agl
’s road
map, see [22].
And finally, to register the entire API to the AGL Application Framework the
afb_binding_v2
structure is automatically generated as follows.
const struct afb_binding_v2 afbBindingV2 = {
.api = "example",
.specification = "",
.info = "Auto generated - Example",
.verbs = verbs,
.preinit = NULL,
.init = init,
.onevent = NULL,
.noconcurrency = 1
};
RAML Parser¶
Fig. 7 presents the internals of the RAML Parser component. Furthermore, the responsibilities of each of the sub-components are stated in Table 5
Name | Responsibility |
---|---|
Root Attributes Parser | Parse the RAML root attributes like; title and base URI. |
Methods Parser | Parse the RAML verbs as methods |
Input Parameters Parser | Parse the RAML verbs’ input parameters |
Output Parameters Parser | Parse the RAML verbs’ output parameters |
Types Parser | Parse the RAML verbs’ parameters’ types |
raml2agl main¶
Fig. 8 presents the internals of the RAML2AGL main component. Furthermore, the responsibilities of each of the sub-components are stated in Table 6
Name | Responsibility |
---|---|
Command Line Arguments Parser | Parses the command line arguments to configure the File Generator. |
Templates Filters | Defines Jinja2 Template filters to convert data types from RAML format to C++. |
Files Generator | Passes the JSON model to render the templates to be built and write files to the selected output location. |
[22] | Pedro Cuadra. Raml to agl. URL: https://github.com/pjcuadra/raml2agl. |
[29] | Automotive Grade Linux. Bindings reference. URL: http://docs.automotivelinux.org/docs/apis_services/en/dev/reference/af-binder/afb-binding-references.html. |