The MSF4J team is excited to announce the latest release of WSO2 Microservices Framework for Java (MSF4J) 2.0!
MSF4J is essentially a lightweight, high performance framework for developing and running microservices.
This release comes with a number of major enhancements and features:
- An improved thread model and transport architecture
- Spring and Swagger support
- ExceptionMapper and StreamingOutput support
- More powerful form submission commands
- Circuit Breaker state management based on Nygard’s pattern
Let’s examine these in more detail.
Improved thread model and transport architecture
The default thread model in MSF4J 1.0 included the Netty boss threads handing over the requests to Netty worker threads, and the microservice requests being executed using the Netty worker threads. However, this leads to the problem of the Netty worker thread pool getting exhausted if the threads took long to execute or were blocked. That results in requests being dropped.
With the new thread model, service requests are executed using a separate executor thread pool (application thread pool) by default. There is also the option of handing over the incoming request to an LMAX disruptor which is useful in certain scenarios. As a user, you will have full control over configuring these thread pools.
MSF4J thread model. S in the diagram is your MSF4J service.
MSF4J 1.0 also had a direct dependency on Netty, but with 2.0, we’ve brought in an abstraction called CarbonMessage. CarbonMessage will represent the request and response messages, irrespective of the underlying transport technology.
Spring is a popular framework among developers because it provides a very simple dependency injection (DI) mechanism which makes life easy for developers. We decided to support Spring owing to popular user demand for dependency injection support.
MSF4J now supports a Spring-native programming model. You can now write your MSF4J microservices, Interceptors, ExceptionMappers and configuration as Spring beans and wire them up at runtime.
The standard Spring configuration annotations such as @Component, @AutoWired and other Spring features work with MSF4J, making it easy to bring in other 3rd party libraries and wire them in at runtime. For example, those who are familiar with Spring-JPA can use the Spring-JPA library to integrate the Hibernate ORM framework with a MSF4J service. The Spring sample demonstrates this feature in action.
Swagger is a standard, language-agnostic interface to REST APIs which allows both humans and computers to discover and understand the capabilities of the service without access to source code, documentation, or through network traffic inspection.
This feature allows you to add Swagger annotations to your microservices to enrich the Swagger definition of your service. Please note that if Swagger annotations have not been used, the feature will still generate a basic Swagger definition by going through other JAXRS annotations in your service.
The stockquote service example demonstrates Swagger annotations in action. After running that sample, you can retrieve the Swagger definition of the service by going to http://localhost:8080/swagger?path=/stockquote.
An ExceptionMapper maps a Java exception to an HTTP response that is to be sent back to the invoker of the MSF4J service. This feature allows Java developers to throw business logic exceptions from their MSF4J services, and if there are ExceptionMappers registered to handle such exceptions, the toResponse method in those mappers will be invoked.
Directly returning Java stacktraces to clients is a bad practice. As a best practice, a properly designed HTTP response which doesn’t expose critical internal implementation details or security details should be returned.
ExceptionMapper allows Java developers to write their code using Java best practices, i.e. throw exceptions when exceptional conditions are encountered, and also follow best practices in service design by not exposing internal details by returning stacktraces.
The stockquote service example demonstrates ExceptionMapper in action.
Streaming file download
StreamingOutput gives the developer full control over how the response from your microservice is going to be streamed. You can choose the size of the chunks that are going to be streamed. Depending on the available resources to the JVM, you may select your chunk sizes. For example, smaller chunk sizes will allow you to operate with a lower server side memory footprint. However, note that this may cause the clients to experience higher latencies. The idea is that you can choose a chunk size that is a good tradeoff between memory footprint and latency.
A practical example could be streaming a large file to a client or reading a large number of records from a database and streaming data based on those records.
The FileServer example demonstrates StreamingOutput in action.
FormParam and FormDataParam annotation support
The @FormParam annotation supports HTML form submission with application/x-www-form-urlencoded and multipart/form-data MIME types. The value will be automatically converted to the corresponding parameter type and assigned to that parameter in the MSF4J service operation.
The difference between @FormParam and @FormDataParam is that FormParam can support only Java Strings and primitive types (int, long, Integer, Long etc). The @FormDataParam annotation, on the other hand, can support complex types and Collections, with multipart/form-data content type and support for files along with form field submissions. These can be directly submitted to a MSF4J service and will be handled seamlessly.
The form service sample demonstrates this feature in action.
In certain case, a user may want to have full control over the incoming message stream from form submissions, for performance optimization reasons. This can be achieved using the FormParamIterator. When a FormParamIterator is declared as the only parameter of your service operation, MSF4J will hand over full control of the stream to you. The FormParamIterator is injected via the @Context annotation.
This feature is demonstrated in the form service sample.
Nygard’s circuit breaker pattern defines that rather than wasting valuable resources trying to invoke an operation that keeps failing, the system backs off for a period of time, and later tries to see whether the operation that was originally failing works. This is now supported supported in MSF4J using the Netflix Hystrix library.
Circuit breaker lifecycle
In the context of microservices, a typical usage of circuit breakers would be when one microservice calls another or when a microservice calls out to an external system. In such cases, these calls will be wrapped in Hystrix commands which will take care of handling the circuit breaker state management. The circuit breaker parameters can be configured as per the configurations listed athttps://github.com/Netflix/Hystrix/wiki/Configuration.
This feature is demonstrated in the MSF4J circuit breaker sample.
As you can see, we’ve added quite a bit to the second version of MSF4J. Try out MSF4J 2.0 and let us know what you think – it’s free and open source.