Introducing HttpMate
Nobody wants to write bad code. Nobody starts the application development with the thought “I’m going to create the most entangled and unreadable code and make sure it’s not extendable and hard to modify or navigate through”. One starts with good intentions, probably even having all the Clean Code and SOLID principals in mind. However, compromises start creeping in fast and multiply, usually based on the number of external dependencies involved.
We, at envimate, for one, did not find any framework that would allow us to develop a web application and claim in good conscience that its business logic does not depend on the underlying HTTP server, persistence layer or (de)serialization mechanism (also referred to as “infrastructure code” in DDD).
If you also feel you no longer develop your application, but rather keep “integrating” and “integrating” the framework, fighting its demons and never having time for the actual business logic. If you are also tired of endless refactoring just because a new version of the framework has been released. If you are not sure which annotation to use anymore, and frankly tired of the invasiveness of the HTTP framework you are using, thenHttpMate is for you.
It’s non-invasive, flexible and ultra-extendable. HttpMate offers you 3 modes of handling HTTP requests – UseCase-driven, low-level HTTP and event-driven request handling as well as mixing those modes to get the most out of the feature-rich framework.
Without further adieu, let’s see some code examples.
Low-level HTTP request handling
final HttpMate httpMate = HttpMate.aLowLevelHttpMate() .get("/api/hello", (httpRequest, httpResponse) -> { final Optional<String> name = httpRequest.queryParameters().getQueryParameter("name"); httpResponse.setBody("Hello " + name.orElse("World")); httpResponse.setStatus(OK); }) .build();
This piece uses the low-level HTTP builder of HttpMate, and it just scratches the surface of possibilities.
You can easily register handlers for any path/http method combination. In the handler lambda you have the request and response objects at your disposal and the handler can get as complicated as you need.
Checkout theexamples section of the repository for more information about the low level API.
You’ve probably seen every other HTTP framework providing an easy way of writing little request handlers, and while this is a great way to give an intro to the framework’s syntax and is a great marketing tool, any real-life challenge includes more than “just handling the request with a function call”. The world desperately needs an HTTP framework that would provide a proper abstraction layer betweenrequest handling and business logic, and allow you to not compromise on things that matter – clean architecture and extendability.
UseCase example
HttpMate allows you to “just publish your business logic as an HTTP endpoint”. Let’s explore the UseCase of sending an email to demonstrate that.
We don’t know yet how the HTTP endpoint will look like, but we do know we need an Email object representing the details of the email:
- Sender
- Receiver
- Subject
- Body
and we would need to return, let’s say a Receipt for every email sent:
- TrackingNumber
- Date
and we would have a class responsible for sending the email, that would look something like:
public class SendEmailUseCase { ... public Receipt sendEmail(final Email email) { ...} ... }
Now you can use the HttpMate builder to publish that Use Case – given that you’ve decided which URL and which HTTP methods are going to be responsible for serving this UseCase to the user:
final HttpMate useCaseDrivenHttpMate = HttpMate.anHttpMateConfiguredAs(UseCaseDrivenBuilder.USE_CASE_DRIVEN) .post("/api/sendEmail", SendEmailUseCase.class) .mappingRequestsAndResponsesUsing( mapMate() ... ) .build();
The first part is quite self-explanatory: invoke the SendEmailUseCase upon POST to “/api/sendEmail”.
And “How come, the SendEmailUseCase gets a valid instance of Email?” the bright minded reader might ask.
That is a valid question indeed, it’s the most complicated technical detail of this example and where the devil is hiding. To keep this article focused on HttpMate and an easy read, we asked another mate to fight off that devil. We will talk about that brave mate inanother post.
By default, HttpMate uses the empty default constructor of the UseCase class to initialize it. That said, HttpMate can be easily configured to use any dependency injection mechanism by adding a call to the builder; the following example demonstrates that using Google Guice:
final HttpMate useCaseDrivenHttpMate = HttpMate.anHttpMateConfiguredAs(UseCaseDrivenBuilder.USE_CASE_DRIVEN) .post("/api/sendEmail", SendEmailUseCase.class) .mappingRequestsAndResponsesUsing( mapMate() ) .configured(toCreateUseCaseInstancesUsing(INJECTOR::getInstance)) .build();
Checkout this github repo for more elaborate example of the SendEmailUseCase.
Final Words
There are a lot of frameworks out there, providing HTTP endpoint configuration, however, most of the time the nice and shiny demo does not survive the hardships of reality. We wanted to create something that while easy and intuitive to configure can support you in your application development, provide you with the tools to accomplish clean code and architecture and be a good foundation for your Use Cases.
And that’s not all! Remember how I told you this just scratches the surface of possibilities? HttpMate, together with other “mates” we are working on has more to offer: websockets, event-driven approach to HTTP, multipart requests done right, handling request and response validated serialization and deserialization, etc. Stay tuned for more articles about the Mate family!
We will be happy to hear your feedback and receive your contributions, so checkout out GitHub repo forHttpMate and Happy Coding!
Published on Java Code Geeks with permission by Envimate, partner at our JCG program. See the original article here: Introducing HttpMate Opinions expressed by Java Code Geeks contributors are their own. |