Table of Contents....5
About the Author....15
About the Technical Reviewer....16
Acknowledgments....17
Introduction....18
Chapter 1: Setting Up a Development Environment....19
Get Started with IntelliJ IDEA Community Edition....19
Download and Run IntelliJ IDEA....20
Create a New Kotlin Project with IntelliJ IDEA....20
Kotlin Hello, World!....25
Kotlin Naming Conventions....25
Write Some Code....25
Run Your Code with IntelliJ IDEA....27
Run Your Code with Gradle....28
IntelliJ IDEA Tips and Tricks....29
Look Out for the Progress Bar....30
Remember to Refresh the Gradle Project in IntelliJ IDEA....31
Embrace Auto-completion in IntelliJ IDEA....32
Chapter 2: Setting Up the Web App Skeleton....34
Web Server Hello, World!....35
Choosing Ktor....35
Add the Ktor Library....35
Start a Web Server....36
Extracting to a Separate Function....37
Using Lambdas....38
Named Arguments Instead of Magic Numbers and Booleans....39
Run Your Web App....40
Logging....41
Loggers on the Java Platform....41
Configure Logging in Your Web App....42
Write to the Log from Your Own Code....45
A Note on “Magic” XML Config Files....47
Useful Error Pages....48
Chapter 3: Configuration Files....51
Create a Configuration File....52
The Configuration File Anatomy....52
Reading Values from Your Configuration File....53
Make the Configuration Fail Early and Type-Safe....54
Store Configuration in a Data Class....55
Load Config into the Data Class....56
Kotlin Null Safety....56
Kotlin Platform Types....57
Use the Data Class in Your Web App....58
Use let Blocks to Avoid Intermediate Variables....59
Provide Different Default Values for Different Environments....60
Environment-Specific Config Files....60
Define the Web App Environment....61
Override Defaults with Environment-Specific Config....61
Secret Config Values....62
Don’t Store Secrets in Version Control....62
Logging Config on Web App Startup....65
Format the Output....66
Masking Secrets....66
Writing to the Log....67
Chapter 4: Decoupling Web Handlers from Specific Libraries....69
Your Own HTTP Response Abstraction....70
Representing HTTP Responses....70
Multiple Response Types....71
Convenience Functions for Headers....73
Case-Insensitive Headers....78
The fold Function....79
Destructuring Assignment....80
Connecting to Ktor....81
Ktor Route Mapping....81
Extension Functions....82
Functions Returning Functions....83
Map Headers....84
Map TextWebResponse and Status Code....85
Map JsonWebResponse....86
Using the New Mapping....88
A Note on Overengineering....89
Chapter 5: Connecting to and Migrating SQL Databases....91
Connecting to a SQL Database....92
The Connection Pool....92
Installing the Database Driver....93
Setting Up H2....94
Updating WebappConfig....94
Set Up the Connection Pool....96
Creating a Connection....97
The Initial Schema....98
Installing Flyway....98
Running Flyway During Startup....98
Creating the Initial Schema....100
Managing Schema Changes....101
Don’t Edit Migrations After Run....101
Adding More Schema....102
Adding Non-nullable Columns....102
Backward-Compatible Migrations....104
Insert Seed Data....105
Repeatable Migrations....105
Updating Repeatable Migrations....106
Handling Failed Migrations....107
Failed Migrations Locally....107
Failed Migrations in Production....107
Rerunning Failed Migration....108
Manually Performing Migration....108
Chapter 6: Querying a SQL Database....109
Setting Up Querying....109
Use SQL Directly....110
Installing Kotliquery....111
Mapping Query Results....111
Execute SQL Queries....112
Creating a Session....112
Querying for Single Rows....113
Querying for Multiple Rows....113
Inserting Rows....115
Updating and Deleting....116
Positional vs. Named Parameters....116
Additional Operations....117
Querying from Web Handlers....117
Creating a Helper Function....117
A Note on Architecture....119
Avoid Long-Running Connections....119
Maps vs. Data Classes....120
Passing Around Maps....120
Passing Individual Properties....121
Mapping to a Data Class....122
Database Transactions....125
Creating Transactions....125
Transactions in Web Handlers....126
Type-Safe Transactional Business Logic....127
Nested Transactions....128
Chapter 7: Automated Tests with jUnit 5....130
Setting Up Your Environment....130
Adding jUnit 5 and kotlin.test....131
Writing a Failing Test....132
Running a Failing Test....132
Making the Test Pass....134
Writing Web App Tests....136
Setting Up the Basics....136
Writing a Failing Test....137
Making the Test Pass....139
Avoiding Leaky Tests....140
Leaky Tests....140
Avoiding Leaks with Transactions....141
Avoiding Leaks with Relative Asserts....144
Test-Driven Development....146
Design and Verification....146
Writing a Failing Test....146
Making the Test Pass....148
Notes on Methodology....148
What About Front-End Tests?....148
Real Database Writes vs. Mocks....149
Unit vs. Integration Tests....150
Chapter 8: Parallelizing Service Calls with Coroutines....151
Preparing Your Web App....151
Implementing a Fake Service....152
Adding a Second Server....152
Understanding Coroutines....154
The delay Coroutine....154
The Problem with Threads....154
Suspending Instead of Locking....155
Coroutine Contexts....155
Coroutines in Ktor....157
Parallelizing Service Calls....158
Adding Dependencies....158
Performing Parallelized Calls....159
Handling Race Conditions....161
Adding to Ktor....161
Mixing Coroutines and Blocking Calls....162
Wrapping Blocking Calls....162
Coroutine Internals....163
Kotlin vs. KotlinX....163
Comparing with Arrow....164
Using Low-Level Continuations....167
Java Platform Implementation Details....168
Chapter 9: Building Traditional Web Apps with HTML and CSS....171
Patterns and Organization....172
Generating HTML....172
Using the kotlinx.html DSL....172
Using the Ktor HTML DSL....173
The Power of the DSL....174
Operator Overloading....175
Adding Custom Tags....176
CSS and Assets....177
Serving Static Files....177
Instant Reloading....180
Reusable Layouts....181
Adding a Layout....182
Using the Layout....183
Adding WebResponse for HTML....184
Implementing HtmlWebResponse....184
Extension Function Precedence....185
Responding with HtmlWebResponse....186
A Note on Abstractions....188
User Security....188
Password Hashing....188
Using Bcrypt for Hashing....189
Updating Your Migrations....192
Adding a Login Form....193
Wiring Up Your Web App....193
Different Types of Sessions....195
Adding a New Ktor Extension Function....196
Configuring Session Cookies....197
Logging In....199
Protecting Routes with Authentication....201
Logging Out....204
Chapter 10: Building API-Based Back Ends....206
Handling API Calls....206
Parsing Input....206
Validating and Extracting Input....207
Avoid Automatic Serialization....209
Internal vs. External APIs....211
Single-Page Apps....211
Hosting Alongside API....211
Hosting Separately with CORS....213
Authenticating Users....215
Native Apps....216
Using Cookies for Authentication....216
Using JWTs for Authentication....216
Performing Authentication....220
Chapter 11: Deploying to Traditional Server Based Environments....222
Packaging as Self-Contained JAR Files....222
What’s a JAR File....222
Self-Contained JAR Files....223
Packaging with Gradle....224
Building the JAR File....224
Executing the JAR File....225
Packaging for Production....226
Building Docker Images....226
Running Docker Images Locally....228
Deploying to Production....229
Chapter 12: Building and Deploying to Serverless Environments....231
Detaching Your Code....232
Separating Handlers from Ktor....232
Basic Structure....233
Detached Web Handlers....235
Run Web Handlers on AWS Lambda....235
Making AWS Lambda Web Handlers....235
Deploying to AWS Lambda....237
Calling Your Existing Handlers....245
Improving Performance....251
Performance and Cold Starts....252
Initialization Time vs. Execution Time....252
Lazy Loading....253
Initializing Correctly....254
Migrations and H2....256
Java Runtime Flags....256
GraalVM, Kotlin/JS, and Kotlin Native....257
Chapter 13: Setup, Teardown, and Dependency Injection with Spring Context....259
Why Spring and Dependency Injection?....260
Setting Up Spring Context....261
Adding Your Data Source....262
lateinit in Kotlin....264
Starting Your Web App....265
Extended Usage....266
Chapter 14: Enterprise Authentication Using Spring Security....268
Preparing Your Web App....268
Setting Up Embedded Jetty....268
Initializing the Servlet....271
Adding Ktor to Your Servlet....272
Using Spring Security....274
Setting Up the Servlet Filter....274
Configuring Spring Security....276
Authenticating Users....278
Filtering Requests....280
Accessing the Logged-In User....281
Chapter 15: Choosing the Right Library....283
What’s a Library?....283
Popularity Is Largely Irrelevant....284
Documentation and Stability Are Important....285
Avoid Following the “X Way”....285
Don’t Shy Away from Platform Libraries....286
Boundaries and Layers....287
Chapter 16: An Assortment of Kotlin Tricks....289
Delegation (by lazy)....289
Inline Functions....290
Reified Generics....292
Contracts....293
And So Much More....294
Appendix A: Using Jooby Instead of Ktor....296
Starting a Server....296
Mapping WebResponse....297
Serving Assets....299
Responding to Requests....300
Authenticating with Forms....301
Authenticating with JWTs....304
Appendix B Using Hoplite Instead of Typesafe Config....305
Loading Config Files....305
Handling JVM Target Version Errors....306
Handling Unknown Environment Variables....307
Masking Secrets....307
Appendix C Using Spek Instead of jUnit 5....309
Writing Spek Tests....309
Structuring Spek Tests....311
Skipping Tests....312
Running Individual Tests....312
Index....314
Welcome to Pro Kotlin Web Apps from Scratch! In this book, you’ll learn how to build professional and production-grade web apps, completely from scratch, without the use of big and unwieldy frameworks.My personal web app journey started with frameworks, but when I learned more about what goes on under the hood and grew weary of fighting framework bugs and limitations, I started teaching myself how to build web apps from scratch instead. As it turns out, frameworks aren’t a requirement!You’re in good hands when you’re building from scratch, thanks to modern programming languages like Kotlin and amazing third-party open source libraries.Back in the day, you needed thousands of lines of boilerplate and XML configuration to wire up a framework-less web app. No wonder people preferred frameworks! Nowadays, though, all you need is a couple of handfuls of explicit code, completely free of bloat and magic, that only does what you tell it to.In Part I, you’ll set up a web app skeleton, completely from scratch. This code base forms the basis for Part II, where you’ll learn a handful of patterns and practical solutions that build on the skeleton from Part I. Part III covers how to choose the right library and Kotlin tips and tricks that I didn’t get to cover in the preceding parts. Finally, three appendixes explain how to replace some of the libraries chosen in Parts I and II, to demonstrate that you have free rein to choose different libraries than me and still write pro Kotlin web apps from scratch.I’ve deliberately kept the chapter about Kotlin tips and tricks in Part III as short as I’ve been able to manage. Instead, you’ll learn Kotlin tips and tricks in Parts I and II, and you’ll learn how to build web apps from scratch alongside explanations of the various Kotlin language constructs you’re using.