Good Java developers learn Java syntax, how to create loops and switches, and can work out a lambda filter stream. But great Java developers need to understand the vast ecosystem of tools and frameworks for collaboration, testing, building, and more.
In Real-World Java®: Helping You Navigate the Java Ecosystem, a team of veteran Java developers delivers a concise and authoritative discussion of the most common frameworks, tools, and techniques used in enterprise Java development shops. The authors provide just enough background and examples to allow you to dive right into the expert guidance on annotations, logging frameworks, observability, performance tuning, testing tools, and collaboration, that real-life commercial Java development typically relies on.
You’ll expand your Java development toolkit with frameworks and utilities like Spring, Git, Prometheus, and Project Lombok. You’ll also discover links to tested, downloadable code examples that demonstrate the skills discussed in the book.
Real-World Java® is the perfect resource for everyone already somewhat comfortable with the language but who wants to familiarize themselves with the tools and frameworks used in contemporary Java software development.
Table of Contents
Introduction xxix
Chapter 1: How We Got Here: History of Java in a Nutshell 1
Introduction 1
Understanding the Stewardship of Java 2
Differentiating Key Java Versions 4
Coding Generics in Java 5 4
Coding with Functional Programming from Java 8 4
Coding Modules from Java 11 5
Coding Text Blocks and Records from Java 17 6
Learning About Virtual Threads from Java 21 7
Working with Deprecation and Retirement 7
Identifying Renames 8
Changing to Jakarta EE 8
Renaming Certifications 8
Understanding the Principles of Change 8
Further References 9
Summary 9
Chapter 2: Getting to Know Your Ide: the Secret to Success 11
Understanding IDE History 12
Starting a New Project 13
Creating a Project from Scratch 13
Creating a Project from Existing Sources 14
Creating a Project from Version Control 15
Adding a Project to Version Control 15
Adding a Module to an Existing Project 16
Creating a Run Configuration 16
Getting to Know Your Keyboard Shortcuts 18
Navigating Your Codebase 19
Copying and Pasting Shortcuts 20
Reordering Code 20
Using Other Helpful Shortcuts 21
Debugging Your Code 22
Debugging a Program 22
Speeding Up Debugger Performance 24
Remote Debugging 25
Debugging with Hot Swap 26
Refactoring Your Code 26
Avoiding Duplicate Code 26
Renaming Members 31
Inlining 31
Changing Signatures: Adding and Removing Parameters 32
Exploiting the Editor 32
Automated Reformatting of Code 32
Organizing Imports 32
Reformatting Code 32
Unwrapping 33
Comparing Code 34
Using Column Mode 34
Extending the IDE 35
Peeking at Eclipse 36
Peeking at VS Code 37
Comparing IDEs 39
Further References 40
Summary 40
Chapter 3: Collaborating Across the Enterprise with Git, Jira, and Confluence 41
Collaborating with Git 42
Introducing Git Basics 42
Learning Key Concepts 42
Differentiating Commits 43
Displaying Git Status 43
Branching 43
Tagging 43
Merging 44
Reading Git Logs 44
Staging Your Changes 44
Installing Git 45
Understanding Git Workflow by Example 45
Fetching, Merging, and Pulling 51
Playing with Branches 53
Resolving Merge Conflicts 54
Using Pull/Merge Requests 55
Using the Git Log 56
Rebasing 57
Cherry-Picking 60
Reverting and Resetting 60
Optimizing with IDE Support 61
Looking at the Commit Window 63
Using the Diff-Viewer Window 64
Creating README Files with Markdown Language 69
Using Gitflow for Collaboration 70
Using Jira for Enterprise Process Collaboration 72
Getting Started with Jira 72
Creating a Project 73
Creating an Issue 74
Linking to an Epic 75
Working with Boards 76
Creating a Sprint 76
Adding Users 78
Adding Columns 78
Using Filters 80
Seeing My Issues 80
Querying with JQL 80
Making Bulk Changes 82
Connecting to Git 83
Working with Confluence, the Enterprise Knowledge Management System 83
Further References 86
Summary 86
Chapter 4: Automating Your Ci/cd Builds with Maven, Gradle, and Jenkins 87
Building with Maven 88
Building a Basic Maven Project 89
Understanding the Maven Repository and Dependencies 90
Differentiating Life-Cycle Phases 92
Exploring the POM 93
Working with Properties 93
Specifying Project Information 93
Understanding Version Numbers 94
Using Common Plugins 94
Configuring a Plugin 94
Recognizing Common Plugins 97
Working with a Parent POM 98
Creating Your Own Parent POM 98
Inheriting from the Parent 98
Working with a Multimodule Project 100
Using Other Maven Features 102
Setting System Properties 102
Using a Bill of Materials 102
Releasing Your Project 103
Getting to Know Maven in the IDE 103
Using IntelliJ 103
Using Eclipse 104
Using VS Code 104
Configuring Maven Settings for the Enterprise 106
Building with Gradle 106
Building a Basic Gradle Project 107
Understanding the Gradle Local Repository and Dependencies 109
Specifying Variables 110
Using the Java Plugin 110
Getting to Know Gradle in the IDE 111
Finding a Dependency 112
Integrating with Jenkins 114
Installing Jenkins 114
Learning Jenkins Terminology 116
Creating Jobs 116
Creating a Simple Freestyle Job 117
Creating a Maven Freestyle Job 119
Creating a Gradle Freestyle Job 122
Creating a Maven Pipeline 122
Creating a Gradle Pipeline 124
Learning About Common Plugins 125
Understanding Other Jenkins Capabilities 126
Organizing Jobs 126
Notifying Users 126
Reading Changes 126
Scanning with Sonar 127
Explaining CI/CD Practices 127
Further References 128
Summary 128
Chapter 5: Capturing Application State with Logging Frameworks 129
Needing to Move Beyond Print 130
Using Java Util Logging 130
Comparing Logging Levels 131
Formatting Values 132
Passing Basic Configuration 133
Setting Logging Destinations 134
Logging Lazily 135
Inheriting Loggers 136
Using Log4j 138
Comparing Logging Levels 139
Formatting Values 140
Passing Basic Configuration 141
Comparing Configuration File Formats 142
Setting Logging Destinations 145
Choosing Logging Output Formats 148
Logging Lazily 148
Using SLF4J 149
Omitting a Logging Framework 149
Specifying SLF4J Simple 150
Comparing Logging Levels 150
Formatting Values 151
Logging Lazily 151
Passing Basic Configuration 152
Using SLF4J with Other Logging Frameworks 152
Using Logback 155
Comparing Logging Levels 156
Passing Basic Configuration 156
Setting Logging Destinations 157
Choosing Logging Output Formats 158
Learning More About Logging 159
Deciding on Coding Standards 159
Designing for Performance 159
Choosing a Language for the Logs 159
Preventing Log Tampering 159
Aggregating and Forwarding Logs 160
Comparing Logging Frameworks 160
Further References 161
Summary 161
Chapter 6: Getting to Know the Spring Framework 163
Configuring Spring 164
Using XML Configuration Files 165
Using Java Configuration Classes 167
Using Component Scanning 169
Customizing Spring Applications with Properties 170
Injecting Properties 170
Configuring Environment-Specific Properties with Spring Profiles 171
Turbocharging Development with Spring Boot 173
Initializing Spring Boot Projects with Spring Initializr 173
Using IntelliJ Initializr Integration 174
Working with Spring MVC 178
Handling Errors in Spring 183
Inspecting Your Application with Actuator 185
Securing Your Application with Spring Security 187
Learning Security Terminology 187
Understanding Spring Security Processing 188
Exploring the Spring Projects 192
Further References 193
Summary 193
Chapter 7: Testing Your Code with Automated Testing Tools 195
Understanding Testing Basics 196
Staging Your Test Directory 196
Configuring JUnit in a Maven Build 197
Configuring JUnit in a Gradle Build 200
Using Test-Driven Development to Explore Tests 202
Learning JUnit 205
Looking at Test Flow 205
Skipping a Test 207
Asserting Logic 207
Using Common Assertions 208
Asserting Exceptions 208
Failing Programmatically 209
Verifying Conditions Using Assume Logic 209
Parameterizing Tests 210
Working with Common Testing Libraries 211
Coding Using AssertJ 211
Coding with JUnit Pioneer Features 212
Disabling Until a Date 213
Retrying a Test 213
Working with System Properties 214
Using Cartesian Test 214
Learning About Other Features 214
Mocking Objects 215
Mocking with Mockito 215
Configuring When/Then 218
Verifying Calls 219
Mocking Concrete Classes 220
Mocking Statics 221
Mocking with EasyMock 221
Mocking with Spring MockMvc 222
Measuring Test Coverage 225
Calculating Code Coverage 225
Seeing Code Coverage in the IDE 226
Running Coverage in the Build 227
Optimizing Your Testing with IntelliJ 228
Looking at Assert Messages 228
Exploring Test Runs 229
Navigating to the Test 229
Generating Test Boilerplate with TestMe 230
Learning Other Testing Concepts 231
Using Behavior-Driven Development 231
Testing Contracts 231
Understanding the Golden Master Pattern 231
Testing Mutations 232
Deciding Between DRY vs. DAMP 232
Further References 233
Summary 234
Chapter 8: Annotation Driven Code with Project Lombok 235
Preparing Your Environment for Lombok 236
Installing in IntelliJ 236
Installing in Eclipse 237
Installing in VS Code 237
Including in Maven or Gradle 238
Compiling from javac 239
Implementing Lombok 239
Converting to the Lombok Way 240
Using @Data: the include-all Annotation 240
Autogenerating Your @Getter and @Setter Methods 241
Using @ToString 243
Using @EqualsAndHashCode 244
Generating Constructors with @AllArgsConstructor, @RequiredArgsConstructor, and @NoArgsConstructor Annotations 244
Weaving Loggers into Your Codebase with @Log and More 245
Delomboking Your Codebase 247
Further References 247
Summary 247
Chapter 9: Parallelizing Your Application Using Java Concurrency 249
Understanding Concurrency Basics 250
Dealing with Thread Contention 252
Coding Atomic Operations 254
Using the volatile Keyword 255
Transitioning Thread States 256
New 256
Runnable 256
Blocked 257
Waiting 257
Timed_waiting 257
Terminated 257
Summarizing Thread States 257
Synchronizing 257
Exploring Heap, Stack, and Metaspace 259
Introducing Concurrent Collections 259
Using Built‐In Concurrency Support in Java Streams 260
Using Concurrency Components to Reduce Complexity 261
Locking with ReentrantLock 261
Controlling Thread Access with Phaser 262
Using Runnable, Callable, and Future 262
Coordinating with ExecutorService 263
Using Fixed‐Count Thread Pools 263
Scheduling with ExecutorService 264
Building Reactive Code with CompletableFuture 265
Functional Interfaces Used by CompletableFuture 265
CompletionStage 268
Putting It All Together with CompletableFuture 269
Introducing Virtual Threads 271
Interthread Communication 276
Learning Concurrency Support in the Spring Framework 278
Using @Async/@EnableAsync 278
Scheduling with @Scheduled/@EnableScheduling 280
Launching Threads with ThreadPoolTaskExecutor 280
Understanding @Transactional 281
Further References 281
Summary 281
Chapter 10: Pattern Matching with Regular Expressions 283
Introducing Regular Expressions 284
Learning Basic Regular Expression Syntax 285
Specifying Common Quantifiers 286
Matching Basic Boundaries 287
Working with Common Character Classes 288
Choosing Options 290
Escaping Characters 290
Using Regular Expressions with Java APIs 291
Calling String Methods 291
Finding Matches 291
Replacing Values 292
Splitting 293
Working with Patterns 294
Finding Matches 295
Replacing Values 296
Splitting as a Stream 298
Controlling Behavior with Flags 298
Exploring Advanced Regular Expression Syntax 300
Looking at Neighboring Text 300
Differentiating Quantifiers 301
Identifying Common Mistakes 304
Coding with Regular Expressions 304
Using with Frameworks and Tools 306
Coding Regular Expressions for Apache Commons Validator 306
Coding Regular Expressions for JUnit 306
Coding Regular Expressions for Log4j 307
Coding Regular Expressions for Bean Validation 307
Coding Regular Expressions for Spring 308
Further References 308
Summary 309
Chapter 11: Coding the Aspect-oriented Way 311
Understanding the Need for Aspects 311
Creating Our First Example 312
Exploring the Pointcut Expression Language 315
* Wildcards 315
.. Wildcards 316
Using @AfterReturning 316
Using @AfterThrowing 317
Using @After 317
Using @Around 317
Using @Pointcut 319
Combining Pointcuts 320
Annotation-Based Pointcuts 321
Further References 323
Summary 323
Chapter 12: Monitoring Your Applications: Observability in the Java Ecosystem 325
Introducing Observability 326
Getting Started with Prometheus 326
Starting the Test Application 326
Installing the Exporter 327
Installing Prometheus 327
Configuring a Scrape 328
Introducing PromQL: The Prometheus Query Language 330
Using Prometheus HTTP APIs 336
Micrometer and Actuator 336
Dependencies for Micrometer and Actuator 337
Creating Custom Metrics 337
Counting Results with Micrometer Counter 337
Capturing Fluctuating Values 338
Bucketing Values with Histograms and Summaries 339
Adding Alert Manager 341
Dashboarding with Grafana 344
Logging and Tracing 347
Introducing Logging 347
Key Concepts in Tracing 349
Tooling 349
Implementing Tracing in Spring Boot Applications 349
Further References 349
Prometheus 349
Other Tools 350
Summary 350
Chapter 13: Performance Tuning Your Services 351
Learning the Concepts and Terminology 352
Benchmarking 352
Benchmarking with Built-In Java APIs 353
Microbenchmarking 354
Tuning JVM Settings 357
Configuring Memory Settings 357
Collecting the Garbage 358
Setting Sizes for Garbage Collection 359
Using Serial Garbage Collection 359
Using Parallel Garbage Collection 359
Using G1GC 360
Testing with JMeter 360
Creating a Test Plan 360
Running the Load Test 363
Analyzing the Results 364
Using JDK Tools 365
Using Java Flight Recorder 366
Visualizing in Java Mission Control 368
Monitoring with JConsole 369
Using VisualVM 370
Reporting with JStat 371
Optimizing Your Application 372
Exploring a Case Study 372
Using SonarQube 374
Considering Performance 375
Further References 375
Summary 376
Chapter 14: Getting to Know More of the Ecosystem 377
Writing Javadoc 378
Comparing JVM Languages 379
Sampling Kotlin 379
Sampling Groovy 380
Sampling Scala 381
Exploring Jakarta EE 381
Comparing Database Types 382
Understanding Relational Databases 382
Understanding NoSQL Databases 384
Learning About Integrations 384
Deploying Java 384
Differentiating Web and Application Servers 385
Using Containers 385
Launching to the Cloud 386
Building REST APIs 387
Creating Web Services 388
Documenting APIs 389
Picking a Virtual Machine 390
Exploring Libraries 390
Securing Your Applications 391
Exploring the OWASP Top 10 391
Comparing Types of Security Tools 393
Staying Informed About Changes 393
Further References 393
Summary 394
Appendix: Reading and Writing Xml, Json, and Yaml 395
Working with XML 396
Learning the XML Format 396
Reading XML with Jackson 397
Writing XML with Jackson 399
Reading and Writing XML with DOM 401
Reading XML with SAX 402
Comparing XML Libraries 403
Working with JSON 404
Learning the JSON Format 404
Reading JSON with Jackson 405
Writing JSON with Jackson 406
Reading and Writing JSON with Gson 407
Comparing JSON Libraries 408
Working with YAML 408
Learning the YAML Format 408
Reading YAML with Jackson 409
Writing YAML with Jackson 410
Reading and Writing with SnakeYAML 410
Comparing YAML Libraries 412
Further References 412
Summary 413
Index 415