OAuth2 in One Sentence OAuth2 lets a user grant a third-party application limited access to their account on another service — without giving the third party their password. Classic example: “Sign in with Google.” Your app never sees the user’s Google password. Google verifies the user’s identity and gives your app a token with limited permissions. The Four OAuth2 Roles flowchart TD RO["**Resource Owner**\nThe user who owns the data\n(e.g. Alice, the Google account owner)"
Continue reading »Java
223 posts in this section
OAuth2 Login: Sign In with Google, GitHub, and Custom Providers
What OAuth2 Login Does OAuth2LoginConfigurer implements the Authorization Code flow for user authentication. When a user clicks “Sign in with Google”: Spring redirects to Google’s /authorize endpoint User authenticates on Google and grants consent Google redirects back to your app with a code Spring exchanges the code for tokens (back channel) Spring fetches the user profile from /userinfo Spring creates an OAuth2User and stores it in the SecurityContext Dependencies <dependency> <groupId>org.
Continue reading »OAuth2 Resource Server: Protecting APIs with Bearer Tokens
What Is a Resource Server? In OAuth2, a Resource Server is an API that accepts access tokens and returns protected resources. It doesn’t issue tokens — that’s the Authorization Server’s job. The Resource Server just validates tokens and enforces access control. flowchart LR Client[API Client\nor SPA/Mobile] -->|"1. POST /token\n{client_id, secret}"| AS[Authorization Server\nGoogle / Okta / Custom] AS -->|"2. access_token"| Client Client -->|"3. GET /api/products\nAuthorization: Bearer {token}"| RS[Your Spring Boot API\nResource Server] RS -->|"
Continue reading »Offset Management: Auto-Commit vs Manual Acknowledgment
Why Offset Management Matters The committed offset determines what happens when a consumer restarts. If the offset is committed too early, a crash before processing completes means events are lost. If it is committed too late, a crash after processing but before committing means events are re-processed. flowchart TD subgraph TooEarly["Commit too early → Data Loss"] E1["Commit offset 43"] --> E2["Process record 42"] --> E3["Crash!"] E4["Restart: resume from 43"] --> E5["
Continue reading »One-to-Many and Many-to-One: The Most Common Relationship
Introduction The one-to-many relationship is the most common in any domain model. An Order has many OrderItems. A Category has many Products. A Customer has many Orders. Understanding @OneToMany and @ManyToOne well — especially bidirectional mapping, collection types, and cascade configuration — is foundational to any JPA application. The Domain Example orders (1) ──────────────── (*) order_items An order has many order items. Each order item belongs to exactly one order.
Continue reading »One-to-One Relationships: @OneToOne in Depth
Introduction A one-to-one relationship means one record in table A corresponds to exactly one record in table B. In JPA this is modelled with @OneToOne. Understanding where the foreign key lives, which side “owns” the relationship, and how cascade operations work is essential before moving to the more complex @OneToMany and @ManyToMany. The Domain Example In the e-commerce system, a Customer has one CustomerProfile containing their preferences and biography. A profile belongs to exactly one customer.
Continue reading »Optimistic and Pessimistic Locking: Handling Concurrent Updates
The Lost Update Problem Two users edit the same product simultaneously: Time User A User B T1 Load product (price=999) Load product (price=999) T2 Change price to 899 T3 Change price to 799 T4 Save → UPDATE price=899 T5 Save → UPDATE price=799 User A’s change is silently overwritten. This is the lost update problem. Both JPA locking strategies prevent it — in different ways. Optimistic Locking with @Version Optimistic locking assumes conflicts are rare.
Continue reading »Optional: Eliminating NullPointerException the Right Way
The Problem Optional Solves NullPointerException is the most common runtime exception in Java, and it is almost always avoidable. Optional<T> is not a magic fix — used incorrectly it becomes a more verbose null check. Used correctly, it encodes the possibility of absence directly in the type system, so callers can never “forget” to handle the empty case. This article covers both how to use Optional and — critically — how not to.
Continue reading »Pagination and Sorting with Pageable, Page, and Slice
Why Pagination Matters Returning all rows from a database table is one of the most common production incidents. A query that works in development with 100 rows silently becomes a 10-second, 2 GB memory spike when production has 2 million rows. Pagination limits how many rows travel from the database to the application at a time. Spring Data JPA makes pagination a first-class feature — pass a Pageable to any repository method and get a Page<T> back.
Continue reading »Parallel Streams: ForkJoinPool, Spliterators, and When NOT to Parallelize
How Parallel Streams Work Parallel streams are one of Java 8’s most misused features. It is tempting to add .parallel() to any slow stream pipeline, but the performance characteristics are counterintuitive: parallel can make things slower for small data, and adding blocking I/O inside a parallel stream can stall the entire JVM. This article explains the mechanics, the cases where parallel genuinely helps, and the patterns to avoid. A parallel stream splits its source into sub-sequences, processes each sub-sequence on a separate thread, and merges the results.
Continue reading »