Java and Cassandra: A Marriage Made for Microservices
Over the years, Apache Cassandra® has been proven as the powerful database of choice, designed to solve tough data challenges where relational databases would fail. Similarly, Java has emerged as the most popular language for building backend applications. However, given the increasing shift toward building cloud-native applications, challenges have emerged that have made it difficult to use Java and Cassandra together.
As a back-end Java developer, it has been painful to directly connect Cassandra to all of your applications. You’ve had to integrate drivers throughout your infrastructure and manage configurations for multiple environments. Cassandra also brought the requirement to open port 9042, incurring the scrutiny of your security team and sometimes creating difficult to trace errors with misconfigured firewalls. On top of it all, you’ve had the headache of deploying to bare metal or VMs, resulting in a heavy app including all the Java Virtual Machine (JVM) elements, classpaths, and operating system dependencies.
The modern way to avoid or reduce this pain is to adopt a cloud-native application development approach. As VMware has helpfully defined: “cloud-native is an approach to building and running applications that exploits the advantages of the cloud computing delivery model.” This includes the concepts of DevOps, continuous delivery, microservices, and containers.
For a Java-based application, taking a cloud native approach begins with deploying Java services into containers. Creating a dependable build of your application code into a single Docker image has revolutionized the way we deploy our applications. New frameworks have emerged to take advantage of how containers work to help Java continue as a viable implementation language for cloud-native applications. DataStax has partnered with VMware to improve Cassandra's integration in Spring Boot and Spring Data and with RedHat to develop the Quarkus Cassandra Extension. These integrations are designed to save you effort, easing your modernization path toward cloud-native.
Ease of use
Both Spring and Quarkus provide initializers that require only a few convenient clicks to jump start a new application or microservice and it's this developer productivity boost that inspired Netflix to standardize on Spring for their applications. These initializers make it easy to find the healthy ecosystem of extensions that "just work" and take care of the boilerplate needed to build containerized backend services. For example, by simply including Spring Cloud Kubernetes or the Quarkus Kubernetes Config dependencies you can leverage Kubernetes ConfigMaps and Secrets directly in your application.
The Cassandra integration in Spring Boot, Spring Data and Quarkus saves you time in the development cycle by taking care of the common tasks that you would otherwise have to write yourself. The table below summarizes the activities that you no longer have to wrestle with when using these frameworks with Cassandra.
Task | Without C* integration | Spring with C* integration | Quarkus with C* integration |
---|---|---|---|
Configure database connection | Custom code or file to configure driver | Configure in application properties (code optional) | Configure in application properties (code optional) |
Access database driver | Custom code for database session | @Autowired CqlSession | @Inject QuarkusCqlSession |
Query the database | Driver Object Mapper(custom code optional) | Automatic POJO to database mappings Driver Object Mapper (custom code optional) | Driver Object Mapper (custom code optional) |
Health checks | Custom code | One line config setting | One line config setting |
Metrics | Custom code | One line config setting | One line config setting |
Reactive Programming | Custom code | Reactive POJO to database mappings | Built-in Mutiny reactive types |
For a quick demonstration of how easy it is to build microservices with Spring and Cassandra and deploy in Kubernetes, see this YouTube video (source available on GitHub).
We’ve also provided a quickstart demo within the Quarkus extension GitHub repository to get you up and running. Recently Red Hat hosted a Quarkus Office hour featuring the Quarkus Cassandra Extension.
Lighter and Faster
Breaking down monolithic applications into microservices is a progression. It's important to consider the pieces of the application that drive the most business value and whether quicker iteration and modernization of those pieces will improve outcomes for the business. Moving to microservices can have many benefits such as allowing teams to enhance functionality autonomously and performance gains from application units with smaller surface areas.
Because the JVM was not built with disposability (fast startup & teardown) in mind, Java has been questioned as a fit for cloud-native applications running in containerized or serverless environments. However, like many technology choices, there are tradeoffs between the productivity of a language that over 10 million seasoned developers have experience with and an alternative that will come with a new learning curve.
Fortunately, Java communities such as Spring, Quarkus and Micronaut are producing new innovations to keep Java relevant in the ephemeral cloud world. Documented strategies to optimize the startup behavior for Spring apps include moving the application classes to a separate filesystem layer when building the docker image. Quarkus in particular has been cited to reduce startup time by 75% and memory consumption by 50% compared to the typical cloud-native stack (and that's without GraalVM native mode).
These new frameworks make it easy to containerize your Java services into a lightweight data microservice, delivering the scalability, resilience, and elasticity of Cassandra, with HTTP API access to the rest of your application. Different parts of your overall microservices architecture can now access data from the data services you have created. Instead of having every bit of application code making direct connections to your Cassandra cluster, you can encapsulate the GET, PUT, POST, and DELETE data operations. Developers consuming your service will no longer need to learn about the underlying database and Cassandra data modeling, reducing the time it takes to deliver applications.
If you are a Java developer, these are exciting new directions in application building. Just because a language is 25 years old, it doesn’t mean it has to get stuck in time. Going cloud-native on your application doesn’t have to mean learning a new language. Creating reactive, scalable microservices is not only easy, you can also bring the right database with you. Combine containerized Java with Cassandra, mix in some Kubernetes and you have a perfect combination for building data services.