Nov 20, 2023
java
The N+1 problem is a common performance issue in JPA. Here’s how to solve it in Spring Data JPA.
Understanding N+1 Problem // N+1 queries: 1 for users + N for each user's posts List<User> users = userRepository.findAll(); for (User user : users) { List<Post> posts = postRepository.findByUserId(user.getId()); // N queries } Solutions 1. Eager Fetching @Entity public class User { @OneToMany(fetch = FetchType.EAGER) private List<Post> posts; } 2. Join Fetch (JPQL) @Query("SELECT u FROM User u JOIN FETCH u.posts") List<User> findAllWithPosts(); 3. Entity Graphs @EntityGraph(attributePaths = {"posts"}) @Query("SELECT u FROM User u") List<User> findAllWithPosts(); 4. Batch Fetching @Entity public class User { @BatchSize(size = 10) @OneToMany(fetch = FetchType.LAZY) private List<Post> posts; } Best Practices Use lazy loading by default Fetch associations when needed Use entity graphs Monitor query performance Use DTO projections Conclusion Solve N+1 problems with:
...
ReadOct 15, 2023
java
Spring WebFlux enables reactive programming in Spring. Here’s when and how to use it.
When to Use WebFlux Use WebFlux When: High concurrency requirements Non-blocking I/O needed Streaming data Microservices with reactive backends Use MVC When: Traditional request-response Blocking operations Existing Spring MVC codebase Simpler mental model needed Basic Setup Dependencies <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency> Reactive Controller @RestController public class UserController { @GetMapping("/users") public Flux<User> getUsers() { return userService.findAll(); } @GetMapping("/users/{id}") public Mono<User> getUser(@PathVariable Long id) { return userService.findById(id); } @PostMapping("/users") public Mono<User> createUser(@RequestBody Mono<User> user) { return userService.save(user); } } Reactive Types Mono // Single value or empty Mono<String> mono = Mono.just("Hello"); Mono<String> empty = Mono.empty(); Mono<String> error = Mono.error(new RuntimeException()); Flux // Multiple values Flux<String> flux = Flux.just("A", "B", "C"); Flux<Integer> range = Flux.range(1, 10); Reactive Repository public interface UserRepository extends ReactiveCrudRepository<User, Long> { Flux<User> findByStatus(String status); Mono<User> findByEmail(String email); } Error Handling @GetMapping("/users/{id}") public Mono<User> getUser(@PathVariable Long id) { return userService.findById(id) .switchIfEmpty(Mono.error(new UserNotFoundException())) .onErrorResume(error -> { // Handle error return Mono.empty(); }); } Testing @SpringBootTest @AutoConfigureWebTestClient class UserControllerTest { @Autowired private WebTestClient webTestClient; @Test void shouldGetUsers() { webTestClient.get() .uri("/users") .exchange() .expectStatus().isOk() .expectBodyList(User.class); } } Best Practices Use reactive types throughout Avoid blocking operations Handle errors properly Use backpressure Monitor performance Conclusion Spring WebFlux provides:
...
ReadSep 10, 2023
java
Java has evolved significantly from Java 8 to Java 25. Here’s a comprehensive guide to the major changes.
Java 8 (2014) Lambda Expressions List<String> names = Arrays.asList("Java", "Python"); names.forEach(name -> System.out.println(name)); Streams API List<String> filtered = names.stream() .filter(name -> name.startsWith("J")) .collect(Collectors.toList()); Optional Optional<String> name = Optional.of("Java"); name.ifPresent(System.out::println); Java 9 (2017) Modules module com.example { requires java.base; exports com.example.api; } Private Methods in Interfaces interface MyInterface { default void method() { helper(); } private void helper() { // Private method } } Java 11 (2018) String Methods String text = " Java "; text.strip(); // "Java" text.repeat(3); // " Java Java Java " HTTP Client HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://api.example.com")) .build(); Java 17 (2021) Sealed Classes public sealed class Shape permits Circle, Rectangle { } public final class Circle extends Shape { } Pattern Matching if (obj instanceof String s) { System.out.println(s.length()); } Java 21 (2023) Virtual Threads Thread.ofVirtual().start(() -> { // Lightweight thread }); Pattern Matching for Switch String result = switch (value) { case Integer i -> "Integer: " + i; case String s -> "String: " + s; default -> "Unknown"; }; Java 25 (2025) Latest Features Enhanced pattern matching Improved performance Better memory management New API additions Migration Guide Update dependencies Test thoroughly Use new features gradually Monitor performance Update tooling Conclusion Java continues to evolve with:
...
ReadAug 15, 2023
java
SOLID principles are fundamental to object-oriented design. Here’s how to apply them in Java.
S - Single Responsibility Principle Bad class User { public void save() { } public void sendEmail() { } public void generateReport() { } } Good class User { // Only user data } class UserRepository { public void save(User user) { } } class EmailService { public void sendEmail(User user) { } } O - Open/Closed Principle Bad class AreaCalculator { public double calculateArea(Object shape) { if (shape instanceof Circle) { // Calculate circle area } else if (shape instanceof Rectangle) { // Calculate rectangle area } } } Good interface Shape { double calculateArea(); } class Circle implements Shape { public double calculateArea() { return Math.PI * radius * radius; } } class Rectangle implements Shape { public double calculateArea() { return width * height; } } L - Liskov Substitution Principle Bad class Bird { public void fly() { } } class Penguin extends Bird { public void fly() { throw new UnsupportedOperationException(); } } Good interface Bird { void eat(); } interface FlyingBird extends Bird { void fly(); } class Sparrow implements FlyingBird { public void fly() { } } class Penguin implements Bird { // No fly method } I - Interface Segregation Principle Bad interface Worker { void work(); void eat(); void sleep(); } class Robot implements Worker { public void eat() { } // Not applicable public void sleep() { } // Not applicable } Good interface Workable { void work(); } interface Eatable { void eat(); } class Human implements Workable, Eatable { public void work() { } public void eat() { } } class Robot implements Workable { public void work() { } } D - Dependency Inversion Principle Bad class UserService { private MySQLDatabase database; public UserService() { this.database = new MySQLDatabase(); } } Good interface Database { void save(User user); } class UserService { private Database database; public UserService(Database database) { this.database = database; } } Conclusion SOLID principles help you write:
...
ReadJul 20, 2023
java
Java is often criticized for verbosity, but modern Java can be concise. Here’s how to write cleaner code.
Modern Java Features Records (Java 14+) // Old way public class User { private String name; private String email; public User(String name, String email) { this.name = name; this.email = email; } // Getters, equals, hashCode, toString... } // New way public record User(String name, String email) { } Pattern Matching (Java 17+) // Old way if (obj instanceof String) { String s = (String) obj; System.out.println(s.length()); } // New way if (obj instanceof String s) { System.out.println(s.length()); } Switch Expressions (Java 14+) // Old way String result; switch (day) { case MONDAY: case FRIDAY: result = "Weekday"; break; default: result = "Weekend"; } // New way String result = switch (day) { case MONDAY, FRIDAY -> "Weekday"; default -> "Weekend"; }; Best Practices Use Streams // Old way List<String> filtered = new ArrayList<>(); for (String name : names) { if (name.startsWith("J")) { filtered.add(name.toUpperCase()); } } // New way List<String> filtered = names.stream() .filter(name -> name.startsWith("J")) .map(String::toUpperCase) .toList(); Use Optional // Old way String result = null; if (user != null && user.getName() != null) { result = user.getName().toUpperCase(); } // New way String result = Optional.ofNullable(user) .map(User::getName) .map(String::toUpperCase) .orElse(null); Conclusion Modern Java is concise when you:
...
ReadJul 10, 2023
performance
This article summarizes the DEV post “Key Performance Metrics for Web Apps and How to Measure Them,” focusing on the most important signals and how to capture them.
Core metrics LCP (Largest Contentful Paint): loading speed; target < 2.5s p75. INP/TTI (Interaction to Next Paint / Time to Interactive): interactivity; target INP < 200ms p75. FCP (First Contentful Paint): first visual response. TTFB (Time to First Byte): server responsiveness. Bundle size & request count: total transferred bytes and requests. Measurement toolbox Lighthouse: automated audits; budgets and suggestions. WebPageTest: multi-location runs, filmstrips, waterfalls. RUM (GA or custom): real-user timing for live traffic. React profiler & perf tools: find slow renders/update frequency. Webpack/Vite bundle analyzer: visualize bundle composition and dead weight. Optimization reminders Ship less JS/CSS; enable tree shaking/code splitting. Compress and cache static assets; serve modern image formats. Trim request count; inline critical CSS for hero; defer non-critical JS. Watch layout stability; reserve space to avoid CLS hits. Set and enforce budgets (JS gz < 200KB, LCP < 2.5s p75, INP < 200ms). Takeaway: Track a small, high-signal set of metrics with both lab (Lighthouse/WPT) and field (RUM) data, then enforce budgets so regressions fail fast.
ReadJun 10, 2023
java
Validation is crucial in Spring Boot applications. Here’s a complete guide to using @Valid and @Validated.
Basic Validation Dependencies <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency> Bean Validation public class CreateUserRequest { @NotBlank(message = "Name is required") private String name; @Email(message = "Invalid email format") @NotBlank private String email; @Min(value = 18, message = "Age must be at least 18") @Max(value = 120, message = "Age must be at most 120") private Integer age; } @Valid vs @Validated @Valid @PostMapping("/users") public ResponseEntity<User> createUser(@Valid @RequestBody CreateUserRequest request) { // Validates request object } @Validated @RestController @Validated public class UserController { @GetMapping("/users/{id}") public User getUser(@PathVariable @Min(1) Long id) { // Validates path variable } } Custom Validators @Target({ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy = PhoneNumberValidator.class) public @interface PhoneNumber { String message() default "Invalid phone number"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; } public class PhoneNumberValidator implements ConstraintValidator<PhoneNumber, String> { @Override public boolean isValid(String value, ConstraintValidatorContext context) { return value != null && value.matches("^\\+?[1-9]\\d{1,14}$"); } } Validation Groups public interface CreateGroup {} public interface UpdateGroup {} public class UserRequest { @NotNull(groups = UpdateGroup.class) private Long id; @NotBlank(groups = {CreateGroup.class, UpdateGroup.class}) private String name; } @PostMapping("/users") public ResponseEntity<User> create(@Validated(CreateGroup.class) @RequestBody UserRequest request) { // Only validates CreateGroup fields } Error Handling @RestControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(MethodArgumentNotValidException.class) public ResponseEntity<ErrorResponse> handleValidation( MethodArgumentNotValidException ex) { Map<String, String> errors = new HashMap<>(); ex.getBindingResult().getFieldErrors().forEach(error -> errors.put(error.getField(), error.getDefaultMessage()) ); return ResponseEntity.badRequest() .body(new ErrorResponse("Validation failed", errors)); } } Best Practices Validate at controller level Use appropriate annotations Create custom validators Handle validation errors Use validation groups Conclusion Spring Boot validation provides:
...
ReadMay 22, 2023
mongodb
MongoDB performance optimization requires a systematic approach to identify bottlenecks, analyze query patterns, and implement effective indexing strategies. This guide covers profiling techniques, index optimization, and load testing methodologies.
Understanding MongoDB performance MongoDB performance depends on several factors:
Query patterns: How queries are structured and what operations they perform Index usage: Whether queries can leverage indexes effectively Data volume: Size of collections and documents Hardware resources: CPU, memory, and disk I/O capacity Connection pooling: How applications manage database connections Profiling MongoDB queries Enable profiling MongoDB’s profiler collects detailed information about query execution:
...
ReadMay 15, 2023
react
Optimizing React applications is crucial for better user experience. Here are proven techniques.
1. Memoization React.memo const ExpensiveComponent = React.memo(({ data }) => { return <div>{processData(data)}</div>; }, (prevProps, nextProps) => { return prevProps.data.id === nextProps.data.id; }); useMemo const expensiveValue = useMemo(() => { return computeExpensiveValue(a, b); }, [a, b]); useCallback const handleClick = useCallback(() => { doSomething(id); }, [id]); 2. Code Splitting React.lazy const LazyComponent = React.lazy(() => import('./LazyComponent')); function App() { return ( <Suspense fallback={<div>Loading...</div>}> <LazyComponent /> </Suspense> ); } 3. Virtualization import { FixedSizeList } from 'react-window'; function VirtualizedList({ items }) { return ( <FixedSizeList height={600} itemCount={items.length} itemSize={50} > {({ index, style }) => ( <div style={style}>{items[index]}</div> )} </FixedSizeList> ); } 4. Avoid Unnecessary Renders // Bad: Creates new object on every render <ChildComponent config={{ theme: 'dark' }} /> // Good: Use useMemo or constant const config = useMemo(() => ({ theme: 'dark' }), []); <ChildComponent config={config} /> Best Practices Memoize expensive computations Split code by routes Virtualize long lists Avoid inline functions/objects Use production builds Conclusion Optimize React apps for better performance! ⚡
Read