After gathering some impressions from research and implementing personal experiments, JUG lectures, talks with colleagues, interviews, etc – I’ve reached the realization that – Java Development and Designing Software feels more like DevOps than anything else.
Performance Optimization
In a Standard Java interviews you may be asked about Algorithmic Complexity. But, this is just warming up and important – when you need to implement an algorithm yourself. Then – it is possible to write tests and handle edge cases. But, in today’s world – there is a library for everything and it is more about choosing the right dependency.
In production – Java developers often employ profiling tools like YourKit, VisualVM, JProfiler to identify performance bottlenecks in their applications and optimize them for better scalability and responsiveness. It is harder to resolve something on production – especially when privacy is a must and the app cannot be just debuged on dev/test – with signing non-discloser agreement.
All of the above is a result of the migration of logic in Micro Services instead of monolith apps – where any subfunctionality could be handled in unit test. Now it must be handled by integration test.
Containerization
Docker has become a standard tool for packaging Java applications into containers, allowing for consistent deployment across different environments. I’ve learned and I am running several applications with Docker Compose. But, It seems – the clouds are more Kubernetes oriented and I’ll need to go beyond self-hosting and learn all the cloud tooling.
Key aspects of performance of containers has become startup/shutdown time – so they could be responsive in the clouds to handle stress loads – with new machines started in less then a second. There are several solutions for this in Java:
- CraC – Modified OpenJDK – that allows snapshoting/checkpoing to the hard – the running JVM, so it could be picked up fast.
- GraaVM – Again – Modified JVM – that compiles to native image + Quarkus
- Micronaut – the same idea as Quarkus – but for the standard JVM
The third and especially the second option – try to escape usage of reflection – a dynamism that is seemed unnecessary and costly in modern software. Only with the first option you may get everything as it is now – without being hit in the balls.
All this increases the learning curve and creates dynamism in the development and software design phase. All of them have different APIs (words) for doing the same thing. You will need to reinvent the wheеl. And you will need to figure out and fight a 1000 more technical struggles not related to valuable client business logic – but to the tech stack of choice.
Microservices Architecture
Having properly designed Micro Service Architecture is getting more important than how every single micro service is implemented. This is because different technology may be chosen for each micro service – getting the best from all worlds.
But, choosing this archtecture may create new problems:
Configuration Management
There are Tools that are used to automate the configuration and management of Java application environments, ensuring consistency and reproducibility across different deployment targets. The Spring way of implementing this is Spring Cloud Config. Docker Compose also could be externalizing configuration tool (I’ve used it in such a way). I don’t have expereince yet with Kubernetes, but, as far as I noticed – there are solutions for it also like:
- https://www.terraform.io/use-cases/infrastructure-as-code
- AWS CloudFormation
- Ansible,
- Puppet,
- Chef
Monitoring and Logging
In a micro service application with a lot of modules – logging and monitoring how all the modules are doing is increasingly important. I’ve implemented a tool for this for myself, but there are a lot more – public and designed for the clouds:
- Prometheus
- Grafana
- Elasticsearch
- Logstash
- Kibana
- Splunk
So – instead of monitoring the performance and functionality of single machine or software package – you need to do the same on 100 micro units.
Cloud Providers
And to not feel that you don’t have enough things to learn and adapt to – here are the top cloud providers:
- Amazon AWS
- Microsoft Azure
- Google Firebase / Cloud Services
All of them having specific implementations and variations of Database, Messaging, Lambda, Deployement tools and services.
CI/CD + Testing + Security
As a Java Developer you will not be responsible only for unit tests of your own separate micro service. There should be also integration tests – so – before getting the software to QA and prod – you may know that The Micro Services work together. The CI/CD pipleline may also check vulnerabilities in used dependencies.
- I’ve personally used Jenkins and GitHub, but there are also
- Travis CI
- GitLab Ci/CD
- CircleCI
Besides Dependency security – there are also – the Standard Security Vulnerabilities that you must take care with (or some equivalent) of Spring Security.
- authentication and authorization checks (the most popular way of doing this is JWT) – to prevent unauthorized access
- On the Front End – Escaping content – to prevent Cross Site Scripting
- In the Database – Escaping Parameters to prevent SQL Injection
- Again something that could be handled in the Database – every read or write must contain a parameter from the accessing user (first bullet)
So – if you want to be a Java Developer – sooner or later you will understand that Coding in Java may become the least thing that you do.
The Audio files in this blog post are generated with my OpenAI Wrapper: https://programtom.com/dev/product/gpt-spring-boot-micro-service/