Microservices Are Not Magic-Driven
Learn how to use the Cricket Microservices Framework to handle HTTP requests in microservices and how to adapt it to your needs.
Join the DZone community and get the full member experience.
Join For FreeSoftware is not driven by "magic that just happens." It works thanks to well-designed, reliable mechanisms. As software engineers, we should not build solutions based solely on trust in the frameworks we use. Instead, we should strive to have a good understanding of how the components we use work.
The Cricket Microservices Framework offers a simple and clear mechanism for handling HTTP requests. Thanks to that, we have full control over the created service. Moreover, we can relatively easily adapt this mechanism to specific requirements.
Configuration
Note: In the examples, we will use the Docker image, which will allow us to skip the aspects of installation and running the test service. For those interested, I refer to the source materials at the end of the article.
Let's start with starting the microservice with the default set of features available by REST API.
$ docker run --name mycricket -d -p 127.0.0.1:8080:8080 \
gskorupa/cricket-microsite:latest
The configuration of the running service can be downloaded by referring to the API, after obtaining the session token.
# Log in to the default administrator account
$ echo admin:cricket|base64
YWRtaW46Y3JpY2tldAo=
$ curl -k -H "Authentication: Basic YWRtaW46Y3JpY2tldAo=" -H "Accept: text/plain" -X POST "http://localhost:8080/api/auth"
YWRtaW46MTUyNTQ3MTg0MDQzMA==
# Get configuration
$ curl -i -H "Authentication: YWRtaW46MTUyNTQ3MTg0MDQzMA==" http://localhost:8080/api/system/config
{
"id":"Microsite",
"service":"org.cricketmsf.services.Microsite",
"comment":"most of the service properties and adapters removed for clarity of the example",
"properties":{
"filter":"org.cricketmsf.microsite.auth.SecurityFilter",
"restricted-resources":"DELETE@/api/auth GET@/api/user PUT@/api/user DELETE@/api/user *@/api/cm *@/api/alert *@/api/system"
},
"adapters":{
"StatusService":{
"name":"StatusService",
"interfaceName":"HttpAdapterIface",
"classFullName":"org.cricketmsf.in.http.StandardHttpAdapter",
"properties":{
"silent-mode":"true",
"context":"/api/status"
}
},
"SystemService":{
"name":"SystemService",
"interfaceName":"HttpAdapterIface",
"classFullName":"org.cricketmsf.microsite.in.http.SystemApi",
"properties":{
"silent-mode":"false",
"context":"/api/system"
}
}
}
}
Let's look at the configuration of the StatusService
adapter. The $.adapters.StatusService.properties.context
element defines the context (endpoint) at which this adapter provides its API. In this way we configure each "inbound" adapter, i.e. adapters which are the source of events that require handling by the service.
Note: For the sake of clarity of the example above, the elements that do not matter are removed.
Microservice configuration is not part of the class's source code, but is stored in a separate file. This approach is different from the popular use of annotations, but deeply justified by practical considerations. Separating the source code from the configuration allows for example using the same code in different environments. In this way, just run the service with another configuration file to match the other conditions.
Let's check the operation of the selected adapter. Assuming that the Docker container is still running, we can, for example, check the status of the site with the command:
$ curl -H "Accept:text/plain" http://localhost:8080/api/status
HTTP/1.1 200 OK
Access-control-allow-headers: Authentication
Pragma: no-cache
Access-control-max-age: 1728000
Date: Thu, 17 May 2018 17:47:44 GMT
Access-control-allow-methods: POST, GET, OPTIONS, DELETE, PUT
Last-modified: Thu, 17 May 2018 19:47:44 CEST
Content-type: text/plain; charset=UTF-8
Access-control-allow-origin: *
Access-control-allow-credentials: true
Content-length: 4
OK
Handling HTTP Requests
An incoming HTTP request is routed to the adapter whose context matches the path in the request. The adapter passes the RequestObject to the dedicated method of the service, receives the result wrapped in the Result object, serializes the included data and builds the response. Finally, the response is returned to the client who sent the HTTP request.
We will discuss each activity a little bit more.
request approved?
When a request is received by the HTTP daemon embedded in the microkernel, it is first analyzed by a security filter. You can specify your filter class to check the request.
parse request parameters
Then another filter parses the request and extracts all parameters.
is handler method defined?
The RequestObject goes to the adapter, which searches for the dedicated method of the service. The method is annotated with the adapter name and the HTTP request method name.
execute handler method
The method is run as part of a microkernel, so it can also trigger the functionality of other adapters. The result is the Result object containing the HTTP response code and an optional data object.
set response type
The adapter sets response type based on the "Accept" header of the request. You can override this adapter method to apply specific rules.
is removed or not found?
When the response code is 301, 302, or 404, the response is returned immediately to the HTTP client.
format response
The response data object is serialized to text representation based on "Accept" header of the request. Default is "application/json." You can override this adapter method to provide different data serialization and response formatting.
Conclusion
I hope that this article encouraged you to learn about the architecture of used libraries and frameworks, instead of just trusting it. I also hope that I have encouraged you to further experiment with the Cricket Microservices Framework and use it to build your microservices.
The way Cricket processes the HTTP requests is simple and easy to trace. And the underlying microkernel code of the framework is so small that even if you need to change the solution at the last minute, it will not be a great disaster.
Published at DZone with permission of Grzegorz Skorupa. See the original article here.
Opinions expressed by DZone contributors are their own.
Trending
-
Using Render Log Streams to Log to Papertrail
-
Merge GraphQL Schemas Using Apollo Server and Koa
-
Knowing and Valuing Apache Kafka’s ISR (In-Sync Replicas)
-
Alpha Testing Tutorial: A Comprehensive Guide With Best Practices
Comments