Java
42 items
Series Posts
Part 0: The Azure Ascent: A Backend Engineer's Journey to Cloud Mastery
Welcome to the Azure Ascent—a comprehensive 6-part tutorial series for experienced backend engineers. Follow Marcus as he builds CloudVault, a fintech platform, from the ground up on Azure. This series combines deep conceptual explanations with 40+ production-ready Java code examples, taking you from fundamentals through enterprise-grade deployment.
Part 1: Java 8: The Functional Revolution
Java 8 was the most transformative release in the language's history — introducing lambda expressions, the Stream API, Optional, default interface methods, and a brand-new Date/Time API. This part covers every major feature with deep conceptual explanations and practical examples.
Part 0: Kotlin for Java Survivors: Life After Semicolons
A 16-part series for senior Java and Spring developers learning Kotlin 2.4. Follow Kabir, a 14-year Java veteran, from culture shock to shipping two Spring Boot 4.1 services with Kafka, Qdrant, Spring AI and LangChain4j.
Part 0: Python for Java Developers: From Streams to Tensors
A 10-part, example-driven Python series for seasoned Java and C# developers moving into data science, ML and AI. Follow Arjun, a Java architect pulled into a fraud-detection ML project, from culture shock to PyTorch.
Part 1: The Summit Awaits — Azure Fundamentals & Core Concepts
Marcus begins his Azure journey by understanding the platform's organizational model. We explore subscriptions, resource groups, regions, and the Azure Resource Manager. Learn how Azure's architecture differs from AWS and why these foundational concepts matter for your designs.
Part 2: Java 9: Modules, JShell, and a Smarter Platform
Java 9 introduced Project Jigsaw — the Java Platform Module System — fundamentally restructuring the JDK itself. It also brought JShell (the first REPL for Java), convenient collection factory methods, a new HTTP client, and a raft of API improvements.
Part 1: "Life After Semicolons" — Syntax, Control Flow and the Build
Kabir's first Kotlin pull request is Java with the semicolons left in. We set up a Kotlin 2.4 Gradle build, see what top-level functions compile to, and cover val/var, types without primitives, strings, default arguments, if/when/try as expressions, ranges and loops.
Part 1: "The Culture Shock" — Names, Objects and the Runtime
Arjun's first Python code review goes badly. We cover how Python executes code, why variables are names bound to objects, mutability and aliasing, is vs ==, truthiness, numeric surprises, modules, and a proper project setup with uv.
Part 2: Building the Engine — Azure Compute Services
CloudVault needs to deploy its microservices. Marcus explores four compute options—Virtual Machines, App Service, Azure Functions, and Containers. We build a production-ready Java Spring Boot API and learn when to use each service for different workloads.
Part 3: Java 10: Local-Variable Type Inference with var
Java 10 was a focused release, best known for introducing the var keyword — local-variable type inference. While small in scope, var meaningfully reduced verbosity in everyday Java code. This part covers var in depth, along with the other improvements in Java 10.
Part 2: "The Billion-Dollar Fix" — Null Safety and the Type System
A NullPointerException from a Java supplier SDK crashes Kabir's Kotlin code. We cover nullable types and the safe-call operators, what they compile to, smart casts and their limits, platform types and JSpecify, lateinit vs lazy, Any/Unit/Nothing, and == vs ===.
Part 2: "Collections Without Ceremony" — Lists, Dicts, Sets and Comprehensions
The Streams API, translated. Lists, tuples, dicts and sets; slicing and unpacking; comprehensions as the idiomatic map/filter/collect; sorting with keys; and the collections module — Counter, defaultdict, deque — applied to transaction data.
Part 3: Storing the Treasures — Azure Data & Storage Services
CloudVault's data is growing fast. Marcus explores Azure's data services—SQL Database for relational data, Cosmos DB for globally distributed workloads, and Blob Storage for files. We design a multi-tier data architecture and implement production-ready Java code for each service.
Part 4: Java 11: The New LTS Baseline
Java 11 became the new long-term support baseline, replacing Java 8 for most enterprises. It standardised the HTTP Client, added powerful String and Files utility methods, allowed var in lambda parameters, and introduced the experimental Z Garbage Collector.
Part 3: "Classes Without Ceremony" — Constructors, Properties and Objects
Kabir starts typing getters and Lena stops him. We cover properties instead of fields, accessors and explicit backing fields, primary constructors and init order, final-by-default classes, Kotlin's different protected and internal, objects and companions instead of static, nested vs inner classes, and enums with entries.
Part 3: "Functions Are Values" — Arguments, Closures and Decorators
No more single-method interfaces. Positional, keyword, *args and **kwargs; the mutable-default trap; lambdas; closures and LEGB scoping; and decorators — Python's ten-line answer to Spring AOP — for timing, retries and caching.
Part 4: Connecting the Dots — Azure Networking & Security
Marcus designs a secure, multi-tier architecture for CloudVault. We explore Virtual Networks, Network Security Groups, Azure Key Vault for secrets management, and identity/access control with Azure AD. Learn how to design networks that protect your data while enabling communication between services.
Part 5: Java 12 & 13: Switch Expressions and Text Blocks Begin
Java 12 and 13 were transitional releases that introduced two features in preview that would become cornerstones of modern Java — switch expressions and text blocks (multiline strings). Java 12 also added the Teeing collector and Compact Number Formatting.
Part 4: "Data, Sealed and Value" — Modelling the Domain
Two swapped String arguments make a Pune till ring up toor dal at zero. We rebuild the catalog model with data classes and copy(), destructuring, sealed hierarchies with exhaustive when, value classes that cost nothing until they box, and type aliases, and see what each compiles to.
Part 4: "Objects Without the Ceremony" — Classes, Dunders, Dataclasses and Protocols
Arjun writes a Java-style Transaction class with getters and setters and gets gently mocked. Properties, the Python data model (__repr__, __eq__, __hash__, __len__, __getitem__), @dataclass, class methods, inheritance, enums, and duck typing formalised with Protocol.
Part 5: The Intelligent Layer — Azure AI & Machine Learning
CloudVault wants to add intelligent features to their platform. Marcus explores Azure AI Services (Vision, Language, Speech), Azure OpenAI for LLMs, and Azure Machine Learning. We integrate AI capabilities into a Java backend application and understand when to use pre-built APIs vs. custom models.
Part 6: Java 14 & 15: Records, Text Blocks, and Sealed Classes
Java 14 finalised switch expressions and previewed records and pattern matching for instanceof. Java 15 made text blocks production-ready, introduced sealed classes in preview, and delivered the long-awaited helpful NullPointerExceptions. Together they laid the groundwork for modern Java's data-oriented programming model.
Part 5: "Functions Are Values" — Lambdas, References and Inline
A return inside forEach silently skips half of a pricing audit. We look at what a Kotlin lambda really is: function types instead of functional interfaces, closures over mutable variables, references, fun interfaces, inline functions and where each kind of return goes, plus tailrec and a first look at lambdas with receivers.
Part 5: "The Lazy River" — Iterators, Generators and Context Managers
A 40 GB transaction export will not fit in memory. The iterator protocol, generators and yield, lazy generator pipelines, itertools, exceptions and EAFP, pathlib and csv, and with-statements as Python's try-with-resources.
Part 6: Automating the Climb — Azure DevOps & Deployment
Marcus faces his final challenge—automate everything. We build a complete CI/CD pipeline using GitHub Actions, implement Infrastructure as Code with Bicep, set up monitoring with Application Insights, and establish production-ready deployment practices including blue-green and canary deployments.
Part 7: Java 16 & 17: The Modern LTS Baseline
Java 16 finalised records and pattern matching for instanceof. Java 17 became the new LTS release, finalising sealed classes and introducing pattern matching for switch in preview. Together they define the modern Java baseline that most teams target today.
Part 6: "Extend, Scope, Delegate" — Kotlin's Power Tools
A region code and an audit log threaded through six layers of parameters start a design debate. We cover extension functions and their static dispatch, scope functions with a decision table, context parameters (Stable in 2.4), class and property delegation, operator overloading and infix calls, and build a type-safe product-query DSL with @DslMarker.
Part 6: "Types Strike Back" — Type Hints, Pydantic and Modern Tooling
Arjun misses his compiler. Type hints and what they do (and do not) do at runtime, generics, TypedDict, mypy, runtime validation with Pydantic, project layout with pyproject.toml, ruff, pytest and logging — the Maven-and-JUnit toolkit for Python.
Part 8: Java 18, 19 & 20: Virtual Threads on the Horizon
Java 18, 19, and 20 were bridge releases between the Java 17 and Java 21 LTS versions. They introduced UTF-8 as the default charset, a simple built-in web server, and — most significantly — previewed virtual threads, structured concurrency, and record patterns that would be finalised in Java 21.
Part 7: "Collections Without Collectors" — Collections, Sequences and Strings
A Java utility sorts a "read-only" Kotlin list in place, and a nightly job drowns the garbage collector in intermediate lists. We look at what Kotlin collections are on the JVM, the operations that replace Collectors, sequences versus eager chains versus Streams, arrays, strings and regex, and kotlin.time and Uuid.
Part 7: "Thinking in Arrays" — NumPy, Vectorisation and Broadcasting
Why the for loop is the enemy of numeric Python. The ndarray and its memory model, dtypes, vectorised operations, axes, boolean masks, broadcasting rules, views vs copies, NaN handling, random generators, and cosine-similarity search from scratch.
Part 9: Java 21: The Concurrency Revolution — LTS
Java 21 is a landmark LTS release. It finalised virtual threads (Project Loom), sequenced collections, record patterns, and pattern matching for switch — while previewing string templates and unnamed classes. It is the most feature-rich LTS release since Java 8.
Part 8: "Generics Without Wildcards" — Variance, Reified and Constraints
A Java repository signature full of ? extends and ? super meets Kotlin, and most of the wildcards disappear. We cover declaration-site variance with out and in, use-site and star projections, bounds and where clauses, nullable type parameters and T & Any, erasure and @JvmName, reified type parameters, and build a typed event envelope, router and repository.
Part 8: "DataFrames for SQL Minds" — pandas in Practice
pandas explained through SQL. Series, DataFrames and the Index; selection with loc and iloc; filtering; groupby as GROUP BY and transform as a window function; merge as JOIN; time series and rolling windows; missing data; Copy-on-Write; and building a fraud feature table.
Part 10: Java 22 & 23: Unnamed Variables and Foreign Memory
Java 22 finalised the Foreign Function and Memory API and introduced unnamed variables and patterns. Java 23 continued refining previews including primitive types in patterns and module import declarations. Together they represent the platform's ongoing maturation.
Part 9: "Errors Without Checked Exceptions" — Failure Modelling, Annotations and Reflection
The Java pricing team can't catch an IOException that Kotlin throws. We cover Kotlin's answer to checked exceptions: @Throws for Java callers, try as an expression, require/check/error, Result and runCatching (and their traps), sealed error types, the Experimental unused-return-value checker, annotation use-site targets under the Kotlin 2.4 defaults, and reflection basics.
Part 9: "The First Model" — scikit-learn, Pipelines and Honest Metrics
Sentinel's first fraud model. The estimator API, stratified train/test splits, Pipeline and ColumnTransformer, logistic regression vs random forests, why accuracy lies on imbalanced data, precision-recall and threshold tuning, cross-validation, data leakage, and persisting models.
Part 11: Java 24 & 25: The Next LTS — Simpler, Faster, Safer
Java 24 delivered ahead-of-time class loading and stream gatherers. Java 25 is the next LTS release, finalising scoped values, compact source files, flexible constructor bodies, module import declarations, and primitive type patterns — while introducing compact object headers for significant memory savings.
Part 10: "Suspend Your Disbelief" — Coroutines Fundamentals
Cancelling an import leaves forty supplier calls running on virtual threads. We learn coroutines from the Java side: suspend functions and the state machine the compiler builds, launch/async/runBlocking, structured concurrency, coroutineScope vs supervisorScope, dispatchers and limitedParallelism, cooperative cancellation and timeouts, exception propagation, and how to debug it all.
Part 10: "Into the Deep End" — PyTorch, Concurrency and the AI Toolkit
Tensors, autograd and a hand-written PyTorch training loop. Then the questions a Java architect asks: the GIL, threads vs processes, asyncio for fanning out LLM calls, embeddings and semantic search, validated structured output, and how Python models reach JVM services.
Part 11: "Flowing Data" — Flow, Channels and Virtual Threads
Store managers want live stock numbers, and Kabir reaches for Flux. We cover cold Flow and its operators, back-pressure with buffer, conflate and debounce, hot StateFlow and SharedFlow, channels, Reactor interop in both directions, testing with runTest and virtual time, and a decision table for virtual threads versus coroutines.
Part 12: "Bilingual" — Java Interop, Build Plugins, Testing and Tooling
The Java team wraps Kabir's Kotlin library in a 140-line adapter, and he learns what his API looks like from the other side. We cover calling Java from Kotlin and Kotlin from Java (@JvmStatic, @JvmOverloads, @JvmField, @JvmName, @JvmRecord, @JvmExposeBoxed), the compiler plugins Spring and JPA need, compilerOptions, testing with JUnit, MockK, Kotest and power-assert, and code quality with ktlint, detekt and explicit API mode.