Review of Microservices Frameworks: A Look at Spring Boot Alternatives
Learn more about these Spring Boot alternatives for building Java and Kotlin microservices.
Join the DZone community and get the full member experience.
Join For Freexxxxxxxxxx
private fun createRouting(applicationInfoService: ApplicationInfoService) = Routing.builder()
.register(JacksonSupport.create())
.get("/application-info", Handler { req, res ->
val requestTo: String? = req.queryParams()
.first("request-to")
.orElse(null)
res
.status(Http.ResponseStatus.create(200))
.send(applicationInfoService.get(requestTo))
})
.get("/application-info/logo", Handler { req, res ->
res.headers().contentType(MediaType.create("image", "png"))
res
.status(Http.ResponseStatus.create(200))
.send(applicationInfoService.getLogo())
})
.error(Exception::class.java) { req, res, ex ->
log.error("Exception:", ex)
res.status(Http.Status.INTERNAL_SERVER_ERROR_500).send()
}
.build()
xxxxxxxxxx
webserver {
port: 8081
}
application-info {
name: "helidon-service"
framework {
name: "Helidon SE"
release-year: 2019
}
}
xxxxxxxxxx
ktor {
deployment {
host = localhost
port = 8082
environment = prod
// for dev purpose
autoreload = true
watch = [io.heterogeneousmicroservices.ktorservice]
}
application {
modules = [io.heterogeneousmicroservices.ktorservice.module.KtorServiceApplicationModuleKt.module]
}
}
application-info {
name: "ktor-service"
framework {
name: "Ktor"
release-year: 2018
}
}
xxxxxxxxxx
fun Application.module() {
val applicationInfoService: ApplicationInfoService by inject()
if (!isTest()) {
val consulClient: Consul by inject()
registerInConsul(applicationInfoService.get(null).name, consulClient)
}
install(DefaultHeaders)
install(Compression)
install(CallLogging)
install(ContentNegotiation) {
jackson {}
}
routing {
route("application-info") {
get {
val requestTo: String? = call.parameters["request-to"]
call.respond(applicationInfoService.get(requestTo))
}
static {
resource("/logo", "logo.png")
}
}
}
}
xxxxxxxxxx
fun getApplicationInfo(serviceName: String): ApplicationInfo = runBlocking {
httpClient.get<ApplicationInfo>("http://$serviceName/application-info")
}
xxxxxxxxxx
@Controller(
value = "/application-info",
consumes = [MediaType.APPLICATION_JSON],
produces = [MediaType.APPLICATION_JSON]
)
class ApplicationInfoController(
private val applicationInfoService: ApplicationInfoService
) {
@Get
fun get(requestTo: String?): ApplicationInfo = applicationInfoService.get(requestTo)
@Get("/logo", produces = [MediaType.IMAGE_PNG])
fun getLogo(): ByteArray = applicationInfoService.getLogo()
}
xxxxxxxxxx
plugins {
...
kotlin("kapt")
...
}
dependencies {
kapt("io.micronaut:micronaut-inject-java:$micronautVersion")
...
kaptTest("io.micronaut:micronaut-inject-java:$micronautVersion")
...
}
xxxxxxxxxx
micronaut
application
name micronaut-service
server
port8083
consul
client
registration
enabledtrue
application-info
name $ micronaut.application.name
framework
name Micronaut
release-year2018
xxxxxxxxxx
@ApplicationScoped
class ApplicationInfoService(
...
) {
...
}
xxxxxxxxxx
@ApplicationScoped
@Path("/")
interface ExternalServiceClient {
@GET
@Path("/application-info")
@Produces("application/json")
fun getApplicationInfo(): ApplicationInfo
}
@RegisterRestClient(baseUri = "http://helidon-service")
interface HelidonServiceClient : ExternalServiceClient
@RegisterRestClient(baseUri = "http://ktor-service")
interface KtorServiceClient : ExternalServiceClient
@RegisterRestClient(baseUri = "http://micronaut-service")
interface MicronautServiceClient : ExternalServiceClient
@RegisterRestClient(baseUri = "http://quarkus-service")
interface QuarkusServiceClient : ExternalServiceClient
@RegisterRestClient(baseUri = "http://spring-boot-service")
interface SpringBootServiceClient : ExternalServiceClient
xxxxxxxxxx
@ApplicationScoped
class ConsulRegistrationBean(
@Inject private val consulClient: ConsulClient
) {
fun onStart(@Observes event: StartupEvent) {
consulClient.register()
}
}
xxxxxxxxxx
@Provider
@ApplicationScoped
class ConsulFilter(
@Inject private val consulClient: ConsulClient
) : ClientRequestFilter {
override fun filter(requestContext: ClientRequestContext) {
val serviceName = requestContext.uri.host
val serviceInstance = consulClient.getServiceInstance(serviceName)
val newUri: URI = URIBuilder(URI.create(requestContext.uri.toString()))
.setHost(serviceInstance.address)
.setPort(serviceInstance.port)
.build()
requestContext.uri = newUri
}
}
xxxxxxxxxx
spring
application
name spring-boot-service
server
port8085
application-info
name $ spring.application.name
framework
name Spring Boot
release-year2014
development concept
On the one hand, the framework is not included in the two most popular Java development models (Spring-like (Spring Boot/Micronaut) and Java EE/MicroProfile), which can lead to:
a problem with finding specialists
an increase in the time to perform tasks compared to the Spring Boot due to the need to explicitly configure the required functionality
On the other hand, dissimilarity to “classic” Spring and Java EE lets look at the process of development from a different angle, perhaps more consciously
Micronaut
Pros
AOT — As previously noted, the AOT can reduce the start time and memory consumption of the application as compared to the analog on Spring Boot
Spring-like development model — programmers with experience with Spring framework won’t take much time to master this framework
Application parameters — Good results for all parameters
Additionally:
The Micronaut for Spring project allows, among other things, changing the execution environment of the existing Spring Boot application to the Micronaut (with restrictions)
Quarkus
Pros
Eclipse MicroProfile implementation. See Helidon MP
Application parameters — Good results for all parameters
Additionally:
Spring Boot
Pros
Platform maturity and ecosystem — It's a framework for every day. For most everyday tasks, there is already a solution in the programming paradigm of Spring, that is, in the way that many programmers are used to. Also, development is simplified by the concept of starters and auto-configuration
A large number of specialists in the labor market, as well as a significant knowledge base (including documentation and answers on Stack Overflow)
Perspective — I think many will agree that Spring will remain the leading Java/Kotlin framework in the near future and there is great educational resources available for your team.
Cons
Parameters of application — Application in this framework wasn’t among the leaders, however, some parameters, as noted earlier, you can optimize yourself. It is also worth remembering about the presence of the project Spring Fu, which is in active development and the use of which reduces these parameters
Also, we can highlight common problems that new frameworks have, but Spring Boot does not:
Less developed ecosystem
Few specialists with experience with these technologies
Longer time of implementation of tasks
Unclear prospects
The considered frameworks belong to different weight divisions: Helidon SE and Ktor are microframeworks; Spring Boot and Micronaut are full-stack frameworks; Quarkus and Helidon MP are MicroProfile frameworks. A microframework’s functionality is limited, which can slow down the development. To clarify the possibility of implementing a particular functionality based on a particular framework, I recommend that you familiarize yourself with its documentation.
I don’t dare to judge whether this or that framework will “shoot” in the near future, so in my opinion, for now, it’s best to continue to observe developments using the existing framework for solving work tasks.
At the same time, as was shown in the article, new frameworks win Spring Boot on the considered parameters of the applications. If any of these parameters are critically important for one of your microservices, then perhaps it’s worth to pay attention to the frameworks that showed the best results. However, we should not forget that Spring Boot, firstly, continues to improve, and secondly, it has a huge ecosystem and a significant number of Java programmers familiar with it. Lastly, there are other frameworks not covered in this article: Vert.x, Javalin, etc.
Thank you for reading!
P.S. Thanks to artglorin for helping with this article
Further Reading
Published at DZone with permission of Roman Kudryashov. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments