Developing a simple app with Merly.jl
Merly.jl is a micro web framework, written in Julia. It allows you to build back-end API applications and microservices, easily and quickly.
Installation
To install Merly we only need Julia version 1.5 or higher and execute this small command from Julia’s interactive console.
(@v1.5) pkg> add Merly
If for some reason you have trouble getting the latest version you can use these commands.
using Pkg
Pkg.Registry.add (RegistrySpec (url =
“https://github.com/JuliaRegistries/General"))
Pkg.update()
Pkg.add (Pkg.PackageSpec (; name = “Merly”, version = “1.0.2”))
Programming
In this tutorial we will create a CRUD API for a veterinary, we will only define, for practical purposes, the animals section.
Let’s define the information we need to collect for each animal
Type
Name
We are going to create a structure, which will allow us to create the custom type called Animal
mutable struct Animal
type :: String
name :: String
end
To store our Animal data, we will use a dictionary that will have an integer key as a key, which will function as an ID for our data.
ANIMALS = Dict {Int, Animal} ()
The value of the ID must be increased each time it is used, so we will create a wrapper for the integer, which will allow defining the variable as a constant.
const NEXT_ID = Ref (0)
We will also create a function called getNextId, which will increase the value of NEXT_ID by one each time it is executed.
function getNextId ()
id = NEXT_ID []
NEXT_ID [] + = 1
return id
end
Now, we are going to create the route that allows us to register a new animal in our application. We will define the route “/ createAnimal” with the http POST verb, the function linked to this route will receive an object of type json, which will include the necessary data for the registration of our animal, which are type and name.
Since we will receive this data as text strings and we will have to convert them to a JSON object compatible with Julia, we will define a function that allows the conversion of string to JSON, which we will call: tojson
function tojson (data :: String)
return JSON.parse (data)
end
And we will add it to Merly, so that every time it receives data with the “application / json” header, it executes the tojson function, to process the data automatically.
formats [“application/json”] = tojson
So, we create the route with the @route macro, within it we will create a new ID, we will retrieve the data from the body of the HTTP request to later add the new Animal type data to our dictionary and return the new value of our object with its corresponding ID and the HTTP creation code.
Do not forget that we must pass the data defined in the main program and that we will use in the function associated with the route, such as the JSON library, the ANIMALS dictionary, the getNextId function, and the Animal structure.
@route POST "/createAnimal" (;JSON=JSON,ANIMALS=ANIMALS,getNextId=getNextId,Animal=Animal) begin
id = getNextId()
ANIMALS[id] = Animal(request.body["type"],request.body["name"])
info=Dict()
info["id"]=id
info["type"]= request.body["type"]
info["name"]= request.body["name"]
body = JSON.json(info)HTTP.Response(201
, HTTP.mkheaders(["Content-Type" => "application/json"])
,body= body)
end
Now we are going to recover the data of all the animals registered in our application. For which we will define the route “/ getAnimals” with the HTTP GET verb, which will return the ANIMALS dictionary as a JSON object and for the browser to interpret it as such I will add the header “Content-Type” with the value “application / json “.
@route GET "/getAnimals" (;JSON=JSON,ANIMALS=ANIMALS) begin
HTTP.Response(200
,HTTP.mkheaders(["Content-Type" => "application/json"])
,body=JSON.json(ANIMALS))
end
If now I want to visualize the data of a single animal, I will have to do it through its ID, so in the route I will pass that value and, in the application, I will indicate it through: id, in this way it will allow me to retrieve the value of the ID thanks to the dictionary params belonging to the request structure. Once the application receives the ID, the value will be converted to an integer and the data stored with that key value will be returned as json. Similarly, the “Content-Type” header will be added with the value “application / json”.
@route GET "/getAnimal/:id" (;JSON=JSON,ANIMALS=ANIMALS) begin
id = parse(Int,request.params["id"])
HTTP.Response(200
,HTTP.mkheaders(["Content-Type" => "application/json"])
,body=JSON.json( ANIMALS[id])
)end
To update the data of a previously registered animal, we will use the HTTP PUT verb and the route will be “/ updateAnimal /: id”, in the same way as in the previous case we must specify in the route the ID of the value we want to update, a once with the ID converted to integer, we will take the new data of the animal from the body of the request and we will use it to create a new data and assign it to the previously indicated ID.
@route PUT "/updateAnimal/:id (;JSON=JSON,ANIMALS=ANIMALS,Animal=Animal) begin
id = parse(Int,request.params["id"])
ANIMALS[id] = Animal(request.body["type"],request.body["name"])
HTTP.Response(200)
end
Finally, to delete a previously registered animal we will use the url “/ deleteAnimal /: id” with the HTTP DELETE verb, which will also receive the ID of the animal that we want to delete, for which the function delete! it will be of use to us.
@route DELETE "/deleteAnimal/:id" (;ANIMALS=ANIMALS) begin
id = parse(Int,request.params["id"])
delete!(ANIMALS, id)
HTTP.Response(200)
end
With all the routes defined we will set up the server on port 8086 and the ip 127.0.0.1.
start(host = "127.0.0.1", port = 8086, verbose = true)
$ julia appmerly.jl
[ Info: POST > /createAnimal
[ Info: GET > /getAnimals
[ Info: GET > /getAnimal/:id
[ Info: PUT > /updateAnimal/:id
[ Info: DELETE > /deleteAnimal/:id
[ Info: Listening on: 127.0.0.1:8086
Originally posted on: https://josueacevedo.medium.com/developing-a-simple-app-with-merly-jl-74751ef96662