Operations Core — @Transactional · Spring Security
Operations Core — @Transactional · Spring Security
🎯 What you'll be able to do after this lesson
After finishing this lesson, you'll be able to confidently do the following 3 things.
- ▸✅ Spring Security Filter Chain diagram + JWT authentication filter position
- ▸✅ Method-level authorization control with @PreAuthorize
- ▸✅ Why BCryptPasswordEncoder is the standard (MD5/SHA-1 are forbidden)
Keep these learning objectives as a checklist — close the lesson only when you can answer all of them.
@Transactional — *Spring's Most Powerful Single Line*
The Core Line
A single @Transactional annotation wraps that method in a DB transaction. Automatically rolls back on exception, commits on success. The standard for operations where atomicity matters, such as wire transfers and payments.
Simplest Usage
Spring automatically wraps the DB's BEGIN, COMMIT, and ROLLBACK for you. No more forgetting.
Proxy-Based — Only Applied on External Calls
Spring's @Transactional works via AOP proxy. The transaction is only applied when the method is called from outside.
Calling a method within the same class bypasses the proxy → annotation is ignored.
Solutions:
- ▸Extract to a separate Bean
- ▸Or call the self-proxy via
AopContext.currentProxy()
Propagation — Transaction Within a Transaction
You're already inside a transaction, and you call another @Transactional method — what happens? It's determined by the propagation option.
Most common usage: the default REQUIRED. However, for log and audit records that must be persisted even if the parent rolls back, use REQUIRES_NEW.
Rollback Rules — Only RuntimeException Is Automatic
Default: Only RuntimeException and its descendants (Unchecked) trigger automatic rollback. Checked exceptions like IOException result in a commit.
This is a Java-specific quirk — the distinction barely exists in other languages. Without knowing this, you can easily cause data corruption incidents.
Solution:
Rollback on all exceptions. This is usually the safe default. Kotlin and modern Spring code almost always make this explicit.
readOnly = true — Read-Only Optimization
For methods that only read data, use readOnly=true. JPA skips dirty checking, improving performance. Hibernate FlushMode is also automatically set to NEVER.
Class-level:
This naturally aligns with the CQRS pattern.
5 Common Pitfalls
1. Internal call — Explained above. Method calls within the same class bypass the transaction.
2. Checked exception commit — Specify rollbackFor = Exception.class
3. Private method — Proxy doesn't apply. Must be public.
4. External API call inside a transaction — Holds a DB lock for as long as the external response takes. Recommended to call outside the transaction.
5. Transaction scope too large — Wrapping the entire method holds locks too long. Keep to minimum scope.
Summary
- ▸
@Transactionalenables automatic transactions with one line - ▸Proxy-based → only applied on external calls
- ▸Control nested behavior with propagation options
- ▸Default only rolls back on RuntimeException → recommend
rollbackFor = Exception.class - ▸Read methods should use
readOnly = true
Spring Security — *Authentication and Authorization*
Authentication vs. Authorization
Two terms often confused:
- ▸Authentication = Who are you? Identity verification (login)
- ▸Authorization = Are you allowed to do this? Permission check (admin page access)
Spring Security handles both.
Minimal Configuration (Spring Security 6 / Spring Boot 3)
URL-based permissions, session policy, JWT filter registration — all in one chain.
Login Flow — The Most Common Pattern
1. Password Verification (Authentication Manager)
Key point: hash comparison of passwords using bcrypt. Never store plain text.
2. JWT Issuance + Response
- ▸Access Token — 15 minutes, sent in header with every API call
- ▸Refresh Token — 7 days, stored in httpOnly cookie (XSS protection)
3. Subsequent Requests — JwtAuthenticationFilter
On every request: validate token → store user info in SecurityContext → access via @AuthenticationPrincipal elsewhere.
Method-Level Authorization
Permissions at the method level, not just URL level. SpEL (Spring Expression Language) allows expressing complex rules.
Activate with: @EnableMethodSecurity on your configuration class.
OAuth 2.0 — Social Login
Don't implement it yourself — use Spring Security OAuth2 Client:
Spring handles the entire OAuth flow (redirects, token exchange, user info retrieval). You only map against users in your own DB in the callback.
Common Security Pitfalls
1. Overusing CSRF disable — OK for REST API + JWT. Enable it for session cookie-based setups.
2. CORS too permissive — Never use *. Use an explicit origin list.
3. Storing passwords in plain text — One step from disaster. bcrypt or argon2 is mandatory.
4. JWT secret exposure — Use environment variables. Never hard-code it.
5. SQL Injection — Always use JPA or parameterized queries.
Summary
- ▸Spring Security = the standard for authentication and authorization
- ▸JWT is the modern trend (stateless, mobile-friendly)
- ▸bcrypt for passwords, JWT secret in environment variables, appropriate CSRF and CORS settings
- ▸Method-level authorization uses
@PreAuthorize - ▸Social login is handled by OAuth2 Client with one line
Spring Security Filter Chain · JWT Filter Implementation
The Core of Security — The Filter Chain
Spring Security connects dozens of filters in a chain. When an HTTP request comes in, it passes through every filter in order before reaching the controller.
To add JWT authentication, you need to insert your own filter into the chain.
JWT Filter — Extending OncePerRequestFilter
OncePerRequestFilter guarantees exactly one execution per request. Prevents duplicate execution from Spring's forward and include dispatches.
Registering the SecurityFilterChain
Use .addFilterBefore(...) to insert the filter at the desired position.
Method-Level Authorization — @PreAuthorize
SpEL (Spring Expression Language) lets you express complex authorization conditions. Patterns like "only the user themselves or an ADMIN" can be expressed in a single line.
Summary
- ▸Filter chain — the request processing pipeline
- ▸OncePerRequestFilter — the standard base for custom filters like JWT
- ▸@PreAuthorize — authorization control at the controller and service level
- ▸BCryptPasswordEncoder — passwords must always use bcrypt
When asked in an interview "How have you applied Security?", you should be able to mention these 4 things.
🤖 Try Asking AI Like This
Knowing the concepts from this lesson lets you give specific instructions to AI. Not a vague 'fix this,' but a request with vocabulary — that's where token savings begin.
- ▸"Add a JWT authentication filter (OncePerRequestFilter) to this SecurityConfig"
- ▸"Protect this method with @PreAuthorize('hasRole(ADMIN)')"
- ▸"Register BCryptPasswordEncoder as a Bean"
Why This Reduces Tokens
Without knowing the concepts, even after receiving an AI response, you have to ask "What is that?" again. Those follow-up questions are what consume tokens. Learn the concepts once, and the conversation ends in a single exchange.