What’s New With Jakarta NoSQL? (Part II)
The concept of cloud-native and to run an application with this concept using the latest milestone version of Jakarta EE NoSQL.
Join the DZone community and get the full member experience.Join For Free
Moving to Cloud-Native
Cloud computing has brought many methodologies and techniques that have revolutionized both the business and technical worlds. Among the terms that came up were cloud-native. To meet and cover these expectations in the Java universe, Jakarta EE emerged. The purpose of this post is to talk about the concept of cloud-native and to run an application with this concept using the latest milestone version of Jakarta EE NoSQL.
You may also like: From javax.* to jakarta.*: A Simple Proof of Concept
Like any new concept, there are several concepts with the same name; if you read books or articles about cloud-native, you may not find consensus about it. For example:
"Cloud-native is an approach to building and running applications that exploits the advantages of the cloud computing model."
"Cloud-native is a different way of thinking and reasoning about software systems. It embodies the following concepts: powered by disposable infrastructure, composed of bounded, scales globally, embraces disposable architecture."
— Architecting Cloud Native Applications: Design high-performing and cost-effective applications for the cloud
"In general usage, “cloud-native” is an approach to building and running applications that exploits the advantages of the cloud-computing delivery model. “Cloud-native” is about how applications are created and deployed, not where."
In a mutual consensus around the definitions from several articles, we can say that cloud-native is a term used to describe container-based environments. So cloud-native isn’t related to specific programming languages or frameworks or even to a cloud provider company, but to containers.
What Are the Cloud-Native Best Practices?
When we start to learn a new concept, we usually run to read about best practices to avoid mistakes and any code smell. With Object-Oriented Programming (OOP), we have the design patterns from the gang of four, in Java, we have Effective Java, and when talking about architecture, we have both Clean Code and Clean Architecture. The question is: what are the best practices for cloud-native?
As far as we know, there aren’t best practices related specifically to cloud-native. Since the cloud is close to Agile methodology, there are several practices we can leverage to have a healthy, pain-free application:
- Manifesto for Agile Software Development.
- Continuous Integration.
- Continuous Delivery.
- Domain-Driven Design.
The most well-known practices related to any application that includes cloud computing are inspired by Martin Fowler’s Patterns of Enterprise Application Architecture and Refactoring.
The Twelve-Factor App
- Codebase: One codebase tracked in revision control, many deploys.
- Dependencies: Explicitly declare and isolate dependencies.
- Config: Store config in the environment.
- Backing services: Treat backing services as attached resources.
- Build, release, run: Strictly separate build and run stages.
- Processes: Execute the app as one or more stateless processes.
- Port binding: Export services via port binding.
- Concurrency: Scale-out via the process model.
- Disposability: Maximize robustness with fast startup and graceful shutdown.
- Dev/prod parity: Keep development, staging, and production as similar as possible.
- Logs: Treat logs as event streams.
- Admin processes: Run admin/management tasks as one-off processes.
In summary, there aren’t specific best practices for cloud-native yet, but there are patterns from Agile, microservices, and the twelve-factor app that are useful to follow.
Back to the Code
In the introduction, we explained in detail what cloud-native means, now let’s return to our application and convert it as a cloud-native application. In the first post, we explained the model, the entity, and how Jakarta NoSQL works. So we’ll take it from here and use the easiest way to handle queries with NoSQL and MongoDB with a repository.
To make these services available, we’ll create a rest application with JAX-RS as a resource class.
The application is ready; the last step we’ll create is the configuration class that allows the connection with MongoDB. This is simple, we’ll use Eclipse MicroProfile Configuration that has tight integration capabilities with Eclipse JNoSQL, the reference implementation of Jakarta NoSQL. The Eclipse MicroProfile Config is a solution to externalize configuration from Java applications and makes the third factor easy to follow.
The current configuration of an application can be accessed via ConfigProvider#getConfig().
A Config consists of the information collected from the registered org.eclipse.microprofile.config.spi.ConfigSource s. These ConfigSource s get sorted according to their ordinal. That way we can overwrite the configuration with lower importance from outside.
By default there are three ConfigSources:
- System.getProperties() (ordinal=400).
- System.getenv() (ordinal=300).
- all META-INF/microprofile-config.properties files on the ClassPath. (default ordinal=100, separately configurable via a config_ordinal property inside each file).
Therefore, the default values can be specified in the above files packaged with the application and the value can be overwritten later for each deployment. A higher ordinal number takes precedence over a lower number.
That implies we can have the configuration for the local environment as a file, one to test also as a file, and finally, we can override all this information when we move it to the cloud.
We now have a local configuration, so let’s move our application with Jakarta EE based on the cloud-native approach. To make it really easy, we’ll use a Platform-as-a-Service (PaaS) because you can move your application container-based style in cloud through infrastructure as code (IaC).
Infrastructure as code, or programmable infrastructure, means writing code, which can be done using a high-level language or any descriptive language to manage configurations and automate the provisioning of the infrastructure in addition to deployments.
The Java application is ready to go! The next step is to set the Platform.sh files required to manage and deploy the application. In our first Java post, we took a deep dive into each of these three files in detail:
- One Router (.platform/routes.yaml). Platform.sh allows you to define the routes.
- Zero or more service containers (.platform/services.yaml). Platform.sh allows you to completely define and configure the topology and services you want to use on your project.
- One or more application containers (.platform.app.yaml). You control your application and the way it will be built and deployed on Platform.sh via a single configuration file.
The file that will change on this post is the service file, allowing you to define a database, search engine, cache, and so on. For this project, we’ll set MongoDB instead of MySQL.
To read the environment configuration, Platform.sh supports the configuration-reader that allows easy integration. Platform.sh also supports an array frameworks and languages, including Java. In this post, we’ll override the MongoDB configuration with the Java properties that will add transparency to the application—thanks to the Eclipse MicroProfile Configuration. With these files ready and pushed to the master, Platform.sh will create a set of containers within a cluster.
The application is now ready, so it’s time to move it to the cloud with Platform.sh using the following steps:
- Create a new free trial account.
- Sign up with a new username and password, or login using a current GitHub, Bitbucket, or Google account. If you use a third-party login, you’ll be able to set a password for your Platform.sh account later.
- Select the region of the world where your site should live.
- Select the blank template.
After this wizard, Platform.sh will provision the whole infrastructure to you, and it will offer your project a remote Git repository. The Platform.sh Git-driven infrastructure means it will automatically manage everything your application needs to push it to the master remote repository. After you set up your SSH keys, you only need to write your code—including a few YAML files that specify your desired infrastructure—then commit it to Git, and push.
In this post, we talked about the principles and best practices around cloud-native, which is still an area that needs improvement when we’re talking about a new software development technique. Cloud facilitates software development, and we can see an application running quite simply through Platform.sh and integrated with Jakarta EE. All to say, it’s a great time (a happy new year!) to bring your project to a mature cloud PaaS like Platform.s.
Further ReadingJakarta EE: Generation IV — A New Hope
Opinions expressed by DZone contributors are their own.